Path: blob/master/src/jdk.accessibility/windows/native/toolscommon/AccessInfo.cpp
40957 views
/*1* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include "AccessBridgeCalls.h"26#include "AccessInfo.h"27#include <stdio.h>28#include <time.h>2930LogStringCallbackFP g_LogStringCallback = NULL;3132/*33* returns formatted date and time34*/35char *getTimeAndDate() {36static char datebuf[64];37struct tm *newtime;38char am_pm[] = "AM";39time_t long_time;4041time( &long_time ); /* Get time as long integer. */42newtime = localtime( &long_time ); /* Convert to local time. */4344if( newtime->tm_hour > 12 ) /* Set up extension. */45strcpy( am_pm, "PM" );46if( newtime->tm_hour > 12 ) /* Convert from 24-hour */47newtime->tm_hour -= 12; /* to 12-hour clock. */48if( newtime->tm_hour == 0 ) /*Set hour to 12 if midnight. */49newtime->tm_hour = 12;5051sprintf(datebuf, "%.19s %s\n", asctime( newtime ), am_pm );52return (char *)datebuf;53}545556/*57* displays a message in a dialog and writes the message to a logfile58*/59void displayAndLog(HWND hDlg, int nIDDlgItem, FILE *logfile, char *msg, ...) {6061if (hDlg == NULL || msg == NULL) {62return;63}6465char tmpbuf[HUGE_BUFSIZE];66va_list argprt;6768va_start(argprt, msg);69vsprintf(tmpbuf, msg, argprt);7071SetDlgItemText(hDlg, nIDDlgItem, tmpbuf);7273fprintf(logfile, "\n****************************************\n");74fprintf(logfile, "%s\n", getTimeAndDate());75fprintf(logfile, "%s\n", tmpbuf);76fflush(logfile);7778if ( NULL != g_LogStringCallback )79{80g_LogStringCallback (tmpbuf);81}82}8384/*85* writes a text string to a logfile86*/87void logString(FILE *logfile, char *msg, ...) {8889if (logfile == NULL || msg == NULL) {90return;91}9293char tmpbuf[LINE_BUFSIZE];94va_list argprt;9596va_start(argprt, msg);97vsprintf(tmpbuf, msg, argprt);9899fprintf(logfile, tmpbuf);100fprintf(logfile, "\n");101fflush(logfile);102}103104/*105* safely appends a message to a buffer106*/107BOOL appendToBuffer(char *buf, size_t buflen, char *msg, ...) {108109static char warning[] =110"\nNot enough buffer space; remaining information truncated.\n";111size_t warningLength = strlen(warning) + 1;112113if (buf == NULL || msg == NULL) {114return FALSE;115}116117char tmpbuf[LARGE_BUFSIZE];118va_list argprt;119120va_start(argprt, msg);121vsprintf(tmpbuf, msg, argprt);122123// verify there's enough space in the buffer124size_t spaceRemaining = buflen - strlen(buf) - 1;125if (spaceRemaining <= warningLength) {126strncat(buf, warning, spaceRemaining);127return FALSE;128}129strncat(buf, tmpbuf, spaceRemaining);130return TRUE;131}132133/**134* returns accessibility information for an AccessibleContext135*/136char *getAccessibleInfo(long vmID, AccessibleContext ac, char *buffer,137int bufsize) {138return getAccessibleInfo(vmID, ac, 0, 0, buffer, bufsize);139}140141/**142* returns accessibility information at the specified coordinates in an143* AccessibleContext144*/145char *getAccessibleInfo(long vmID, AccessibleContext ac, int x, int y,146char *buffer, int bufsize) {147148wchar_t tmpBuf[LINE_BUFSIZE];149wchar_t name[LINE_BUFSIZE];150int i, j;151long start;152long end;153154if (buffer == NULL || bufsize <= 0) {155return NULL;156}157buffer[0] = NULL;158159/* ===== AccessBridge / J2SE version information ===== */160161AccessBridgeVersionInfo versionInfo;162BOOL result = GetVersionInfo(vmID, &versionInfo);163164if (result == FALSE) {165appendToBuffer( buffer, bufsize,166"\r\nERROR: cannot get version information", bufsize );167} else {168appendToBuffer(buffer, bufsize, "Version Information:");169appendToBuffer( buffer, bufsize,170"\r\n Java virtual machine version: %ls",171versionInfo.VMversion );172appendToBuffer( buffer, bufsize,173"\r\n Access Bridge Java class version: %ls",174versionInfo.bridgeJavaClassVersion );175appendToBuffer( buffer, bufsize,176"\r\n Access Bridge Java DLL version: %ls",177versionInfo.bridgeJavaDLLVersion );178appendToBuffer( buffer, bufsize,179"\r\n Access Bridge Windows DLL version: %ls",180versionInfo.bridgeWinDLLVersion );181}182183if (ac == (AccessibleContext) 0) {184return buffer;185}186187188/* ===== core AccessibleContext information ===== */189190AccessibleContextInfo info;191if (GetAccessibleContextInfo(vmID, ac, &info) == FALSE) {192appendToBuffer( buffer, bufsize,193"\r\nERROR: GetAccessibleContextInfo failed ", bufsize );194} else {195appendToBuffer( buffer, bufsize,196"\r\n\r\nAccessibleContext information", bufsize );197if (x >= 0 && y >= 0) {198appendToBuffer(buffer, bufsize, " at mouse point [%d, %d]:", x, y);199} else {200appendToBuffer(buffer, bufsize, ":", bufsize);201}202203appendToBuffer(buffer, bufsize, "\r\n Name: %ls", info.name);204if ( getVirtualAccessibleName( vmID, ac, name,205(sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {206appendToBuffer( buffer, bufsize,207"\r\n\r\nERROR: getVirtualAccessibleName", bufsize );208} else {209appendToBuffer(buffer, bufsize, "\r\n Virtual Name: %ls", name);210}211appendToBuffer( buffer, bufsize, "\r\n Description: %ls",212info.description );213appendToBuffer(buffer, bufsize, "\r\n Role: %ls", info.role);214appendToBuffer( buffer, bufsize, "\r\n Role in en_US locale: %ls",215info.role_en_US );216appendToBuffer(buffer, bufsize, "\r\n States: %ls", info.states);217appendToBuffer( buffer, bufsize, "\r\n States in en_US locale: %ls",218info.states_en_US );219appendToBuffer( buffer, bufsize, "\r\n Index in parent: %d",220info.indexInParent );221appendToBuffer( buffer, bufsize, "\r\n Children count: %d",222info.childrenCount );223appendToBuffer( buffer, bufsize,224"\r\n Bounding rectangle: [%d, %d, %d, %d]",225info.x, info.y, info.x + info.width,226info.y + info.height );227228/* top-level window info */229AccessibleContext topAC = getTopLevelObject(vmID, ac);230if (topAC == NULL) {231appendToBuffer( buffer, bufsize,232"\r\nERROR: getTopLevelObject failed", bufsize );233} else {234AccessibleContextInfo topInfo;235if (GetAccessibleContextInfo(vmID, topAC, &topInfo) == FALSE) {236appendToBuffer(237buffer, bufsize,238"\r\nERROR: GetAccessibleContextInfo failed for top-level window ",239bufsize );240} else {241if (getVirtualAccessibleName(vmID, topAC, name,242(sizeof(name) / sizeof(wchar_t)) ) == FALSE) {243appendToBuffer( buffer, bufsize,244"\r\n\r\nERROR: getVirtualAccessibleName",245bufsize );246} else {247appendToBuffer( buffer, bufsize,248"\r\n Top-level window name: %ls",249name );250}251appendToBuffer( buffer, bufsize,252"\r\n Top-level window role: %ls",253topInfo.role ) ;254}255ReleaseJavaObject(vmID, topAC);256257}258259/* ===== AccessibleParent information ===== */260261AccessibleContext parentAC = GetAccessibleParentFromContext(vmID, ac);262if (parentAC == NULL) {263appendToBuffer(buffer, bufsize, "\r\n No parent", bufsize);264} else {265AccessibleContextInfo parentInfo;266if (GetAccessibleContextInfo(vmID, parentAC, &parentInfo) == FALSE) {267appendToBuffer( buffer, bufsize,268"\r\nERROR: GetAccessibleContextInfo failed for parent",269bufsize );270} else {271appendToBuffer( buffer, bufsize, "\r\n Parent name: %ls",272parentInfo.name );273if ( getVirtualAccessibleName( vmID, parentAC, name,274(sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {275appendToBuffer( buffer, bufsize,276"\r\n\r\nERROR: getVirtualAccessibleName",277bufsize );278} else {279appendToBuffer( buffer, bufsize,280"\r\n Parent virtual name: %ls", name );281}282appendToBuffer( buffer, bufsize, "\r\n Parent role: %ls",283parentInfo.role );284}285ReleaseJavaObject(vmID, parentAC);286}287288289/* ====== visible children ===== */290int nChildren = getVisibleChildrenCount(vmID, ac);291if (nChildren == -1) {292appendToBuffer( buffer, bufsize,293"\r\nERROR: GetVisibleChildrenCount failed",294bufsize );295} else {296appendToBuffer( buffer, bufsize,297"\r\n Visible descendents count: %d",298nChildren );299}300301if (nChildren > 0) {302VisibleChildrenInfo visibleChildrenInfo;303if (getVisibleChildren(vmID, ac, 0, &visibleChildrenInfo) == FALSE) {304appendToBuffer( buffer, bufsize,305"\r\nERROR: GetVisibleChildren failed",306bufsize );307} else {308AccessibleContextInfo childACInfo;309for ( int child = 0;310child < visibleChildrenInfo.returnedChildrenCount;311child++ ) {312AccessibleContext childAC =313visibleChildrenInfo.children[child];314if (GetAccessibleContextInfo(vmID, childAC, &childACInfo)) {315if ( getVirtualAccessibleName( vmID, childAC, name,316(sizeof(name) / sizeof(wchar_t))) == FALSE) {317appendToBuffer( buffer, bufsize,318"\r\n\r\nERROR: getVirtualAccessibleName",319bufsize );320} else {321appendToBuffer( buffer, bufsize,322"\r\n Descendent %d name: %ls", child,323name );324}325appendToBuffer( buffer, bufsize,326"\r\n Descendent %d role: %ls",327child, childACInfo.role );328}329ReleaseJavaObject(vmID, childAC);330}331}332}333334/* ===== AccessibleSelection ===== */335336if (info.accessibleSelection == TRUE) {337338int selCount;339AccessibleContext selectedAC;340341appendToBuffer( buffer, bufsize,342"\r\n\r\nAccessible Selection information:",343bufsize );344345if ((selCount = GetAccessibleSelectionCountFromContext(vmID, ac)) != -1) {346appendToBuffer( buffer, bufsize, "\r\n Selection count: %d",347selCount );348349for (i = 0; i < selCount; i++) {350if ( ( selectedAC =351GetAccessibleSelectionFromContext(vmID, ac, i) ) == NULL ) {352appendToBuffer( buffer, bufsize,353"\r\nERROR: GetAccessibleSelectionFromContext failed forselection %d",354i );355} else {356if (GetAccessibleContextInfo(vmID, selectedAC, &info) == FALSE) {357appendToBuffer( buffer, bufsize,358"\r\nERROR: GetAccessibleContextInfo failed for selection %d", i);359} else {360if ( getVirtualAccessibleName( vmID, selectedAC, name,361(sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {362appendToBuffer( buffer, bufsize,363"\r\n\r\nERROR: getVirtualAccessibleName", bufsize);364} else {365appendToBuffer( buffer, bufsize,366"\r\n Selection %d name: %ls", i, name );367}368appendToBuffer( buffer, bufsize,369"\r\n Selection %d role: %ls", i, info.role);370appendToBuffer( buffer, bufsize,371"\r\n Index in parent of selection %d: %d",372i, info.indexInParent );373}374ReleaseJavaObject(vmID, selectedAC);375}376}377}378}379380// ====== Accessible KeyBindings, Icons and Actions ======381382AccessibleKeyBindings keyBindings;383if (getAccessibleKeyBindings(vmID, ac, &keyBindings) == TRUE &&384keyBindings.keyBindingsCount > 0) {385386appendToBuffer( buffer, bufsize,387"\r\n\r\nAccessibleKeyBinding info:", bufsize );388appendToBuffer( buffer, bufsize,389"\r\n Number of key bindings: %d",390keyBindings.keyBindingsCount );391392for (j = 0; j < keyBindings.keyBindingsCount; j++) {393394appendToBuffer( buffer, bufsize,395"\r\n Key binding %d character: %c", j,396keyBindings.keyBindingInfo[j].character );397appendToBuffer( buffer, bufsize,398"\r\n Key binding %d modifiers: %d", j,399keyBindings.keyBindingInfo[j].modifiers );400}401}402403AccessibleIcons icons;404if (getAccessibleIcons(vmID, ac, &icons) == TRUE &&405icons.iconsCount > 0) {406407appendToBuffer( buffer, bufsize,408"\r\n\r\nAccessibleIcons info:", bufsize );409appendToBuffer( buffer, bufsize,410"\r\n Number of icons: %d", icons.iconsCount );411412for (j = 0; j < icons.iconsCount; j++) {413414appendToBuffer( buffer, bufsize,415"\r\n Icon %d description: %ls", j,416icons.iconInfo[j].description );417appendToBuffer( buffer, bufsize,418"\r\n Icon %d height: %d", j,419icons.iconInfo[j].height );420appendToBuffer( buffer, bufsize,421"\r\n Icon %d width: %d", j,422icons.iconInfo[j].width );423}424}425426AccessibleActions actions;427if (getAccessibleActions(vmID, ac, &actions) == TRUE &&428actions.actionsCount > 0) {429430appendToBuffer( buffer, bufsize, "\r\n\r\nAccessibleActions info:",431bufsize );432appendToBuffer( buffer, bufsize, "\r\n Number of actions: %d",433actions.actionsCount );434435for (j = 0; j < actions.actionsCount; j++) {436appendToBuffer( buffer, bufsize, "\r\n Action %d name: %ls",437j, actions.actionInfo[j].name );438}439}440441/* ===== AccessibleRelationSet ===== */442443AccessibleRelationSetInfo relationSetInfo;444if (getAccessibleRelationSet(vmID, ac, &relationSetInfo) == FALSE) {445appendToBuffer( buffer, bufsize,446"\r\nGetAccessibleRelationSet failed.", bufsize );447} else {448int i;449AccessibleContextInfo relInfo;450451if (relationSetInfo.relationCount > 0) {452appendToBuffer( buffer, bufsize,453"\r\n\r\nAccessibleRelationSet information:",454bufsize );455appendToBuffer( buffer, bufsize,456"\r\n Number of relations: %d",457relationSetInfo.relationCount );458}459for (i = 0; i < relationSetInfo.relationCount; i++) {460AccessibleRelationInfo relationInfo =461relationSetInfo.relations[i];462463appendToBuffer( buffer, bufsize,464"\r\n Relation %d key: %ls", i,465relationInfo.key );466appendToBuffer( buffer, bufsize,467"\r\n Relation %d target count: %d", i,468relationInfo.targetCount );469for (j = 0; j < relationInfo.targetCount; j++) {470if (GetAccessibleContextInfo(471vmID, relationInfo.targets[j], &relInfo ) == FALSE) {472appendToBuffer( buffer, bufsize,473"\r\nERROR: GetAccessibleContextInfo failed.",474bufsize );475} else {476// Core AccessibleContext information for relation target477if ( getVirtualAccessibleName( vmID, relationInfo.targets[j],478name, (sizeof(name) / sizeof(wchar_t)) ) == FALSE ) {479appendToBuffer( buffer, bufsize,480"\r\n\r\nERROR: getVirtualAccessibleName", bufsize );481} else {482appendToBuffer( buffer, bufsize,483"\r\n Target %d name: %ls",484j, name );485}486appendToBuffer( buffer, bufsize,487"\r\n Target %d role: %ls", j,488relInfo.role);489}490ReleaseJavaObject(vmID, relationInfo.targets[j]);491492}493}494}495496/* ===== AccessibleValue ===== */497498if (info.accessibleInterfaces & cAccessibleValueInterface) {499500appendToBuffer( buffer, bufsize,501"\r\n\r\nAccessible Value information:", bufsize);502503if ( GetCurrentAccessibleValueFromContext( vmID, ac, tmpBuf,504(sizeof(tmpBuf) / sizeof(wchar_t)) ) == TRUE ) {505appendToBuffer( buffer, bufsize, "\r\n Current Value: %ls",506tmpBuf );507}508if ( GetMaximumAccessibleValueFromContext( vmID, ac, tmpBuf,509(sizeof(tmpBuf) / sizeof(wchar_t))) == TRUE ) {510appendToBuffer( buffer, bufsize,511"\r\n Maximum Value: %ls", tmpBuf );512}513if ( GetMinimumAccessibleValueFromContext( vmID, ac, tmpBuf,514(sizeof(tmpBuf) / sizeof(wchar_t)) ) == TRUE ) {515appendToBuffer( buffer, bufsize,516"\r\n Minimum Value: %ls", tmpBuf );517}518}519520521/* ===== AccessibleTable ===== */522523AccessibleTableInfo tableInfo;524525if ( (info.accessibleInterfaces & cAccessibleTableInterface) ==526cAccessibleTableInterface ) {527if (getAccessibleTableInfo(vmID, ac, &tableInfo) != TRUE) {528appendToBuffer( buffer, bufsize,529"\r\nERROR: getAccessibleTableInfo failed",530bufsize );531} else {532appendToBuffer( buffer, bufsize,533"\r\n\r\nAccessibleTable info:", bufsize );534535int trow = getAccessibleTableRow( vmID,536tableInfo.accessibleTable, 3 );537appendToBuffer( buffer, bufsize,538"\r\n getAccessibleTableRow: %d", trow);539540int tcol =541getAccessibleTableColumn(vmID, tableInfo.accessibleTable, 2);542appendToBuffer( buffer, bufsize,543"\r\n getAccessibleTableColumn: %d", tcol );544545int tindex = getAccessibleTableIndex( vmID,546tableInfo.accessibleTable,5472, 3 );548appendToBuffer( buffer, bufsize,549"\r\n getAccessibleTableIndex: %d",550tindex );551552// Core info553appendToBuffer( buffer, bufsize,554"\r\n table row count: %d",555tableInfo.rowCount );556appendToBuffer( buffer, bufsize,557"\r\n table column count: %d",558tableInfo.columnCount );559560AccessibleTableCellInfo tableCellInfo;561for (int i = 0; i < tableInfo.rowCount; i++) {562for (int j = 0; j < tableInfo.columnCount; j++) {563564if ( !getAccessibleTableCellInfo( vmID,565tableInfo.accessibleTable,566i, j,567&tableCellInfo ) ) {568569appendToBuffer(570buffer, bufsize,571"\r\nERROR: GetAccessibleTableCellInfo failed.",572bufsize );573} else {574appendToBuffer( buffer, bufsize,575"\r\n\r\n AccessibleTable cell[%d,%d] info:",576i, j );577appendToBuffer( buffer, bufsize,578"\r\n Index: %ld", tableCellInfo.index );579appendToBuffer( buffer, bufsize,580"\r\n Row extent: %ld",581tableCellInfo.rowExtent );582appendToBuffer( buffer, bufsize,583"\r\n Column extent: %ld",584tableCellInfo.columnExtent );585appendToBuffer( buffer, bufsize,586"\r\n Is selected?: %ld",587tableCellInfo.isSelected );588589AccessibleContextInfo cellACInfo;590if ( !GetAccessibleContextInfo(591vmID,592tableCellInfo.accessibleContext,593&cellACInfo ) ) {594appendToBuffer( buffer, bufsize,595"\r\nERROR: GetAccessibleContextInfo failed for table cell [%d,%d].",596i, j );597} else {598if ( !getVirtualAccessibleName( vmID,599tableCellInfo.accessibleContext, name,600(sizeof(name) / sizeof(wchar_t)) ) ) {601appendToBuffer( buffer, bufsize,602"\r\n\r\nERROR: getVirtualAccessibleName",603bufsize );604} else {605appendToBuffer( buffer, bufsize,606"\r\n Name: %ls", name );607}608appendToBuffer( buffer, bufsize,609"\r\n Role: %ls",610cellACInfo.role );611}612ReleaseJavaObject( vmID,613tableCellInfo.accessibleContext );614}615}616}617618// Get the column headers619AccessibleTableInfo columnInfo;620if ( !getAccessibleTableColumnHeader(vmID, ac, &columnInfo)) {621appendToBuffer( buffer, bufsize,622"\r\nERROR: getAccessibleTableColumnHeader failed.",623bufsize );624} else {625appendToBuffer( buffer, bufsize,626"\r\n\r\nAccessibleTable column header info:", bufsize );627628// Core info629appendToBuffer( buffer, bufsize,630"\r\n Column header row count: %d",631columnInfo.rowCount );632appendToBuffer( buffer, bufsize,633"\r\n Column header column count: %d",634columnInfo.columnCount );635636}637638// Get the selected rows639int numSelections =640getAccessibleTableRowSelectionCount( vmID,641tableInfo.accessibleTable );642appendToBuffer( buffer, bufsize,643"\r\n\r\nRow selection count: %d",644numSelections );645jint *selections = new jint[numSelections];646647if ( !getAccessibleTableRowSelections( vmID,648tableInfo.accessibleTable,649numSelections,650selections ) ) {651appendToBuffer( buffer, bufsize,652"\r\nERROR: getAccessibleTableRowSelections failed.",653bufsize );654} else {655appendToBuffer(buffer, bufsize, " \r\n Row selections: ");656for (int j = 0; j < numSelections; j++) {657appendToBuffer(buffer, bufsize, " %d", selections[j]);658}659}660661// Get column header info662for (int i = 0; i < columnInfo.columnCount; i++) {663if ( !getAccessibleTableCellInfo( vmID,664columnInfo.accessibleTable,6650, i, &tableCellInfo ) ) {666667appendToBuffer( buffer, bufsize,668"\r\nERROR: GetAccessibleTableCellInfo failed.",669bufsize );670} else {671appendToBuffer( buffer, bufsize,672"\r\n\r\nColumn header [0,%d] cell info.", i );673appendToBuffer( buffer, bufsize,674"\r\n Index: %ld", tableCellInfo.index );675appendToBuffer( buffer, bufsize,676"\r\n Row extent: %ld",677tableCellInfo.rowExtent );678appendToBuffer( buffer, bufsize,679"\r\n Column extent: %ld",680tableCellInfo.columnExtent );681appendToBuffer( buffer, bufsize,682"\r\n Is selected: %ld",683tableCellInfo.isSelected );684685AccessibleContextInfo cellACInfo;686if ( !GetAccessibleContextInfo( vmID,687tableCellInfo.accessibleContext, &cellACInfo ) ) {688appendToBuffer( buffer, bufsize,689"\r\nERROR: GetAccessibleContextInfo failed.",690bufsize );691} else {692if ( !getVirtualAccessibleName( vmID,693tableCellInfo.accessibleContext, name,694(sizeof(name) / sizeof(wchar_t)) ) ) {695appendToBuffer( buffer, bufsize,696"\r\n\r\nERROR: getVirtualAccessibleName",697bufsize );698} else {699appendToBuffer( buffer, bufsize,700"\r\n Name: %ls", name );701}702appendToBuffer( buffer, bufsize,703"\r\n Role: %ls", cellACInfo.role );704}705ReleaseJavaObject(vmID, tableCellInfo.accessibleContext);706}707}708}709}710711/* ===== AccessibleText ===== */712713if (info.accessibleText == TRUE) {714AccessibleTextInfo textInfo;715AccessibleTextItemsInfo textItems;716AccessibleTextSelectionInfo textSelection;717AccessibleTextRectInfo rectInfo;718AccessibleTextAttributesInfo attributeInfo;719720appendToBuffer( buffer, bufsize,721"\r\n\r\nAccessible Text information:", bufsize);722723if (GetAccessibleTextInfo(vmID, ac, &textInfo, x, y) == TRUE) {724appendToBuffer( buffer, bufsize,725"\r\n Mouse point at text index: %d",726textInfo.indexAtPoint );727appendToBuffer( buffer, bufsize,728"\r\n Caret at text index: %d",729textInfo.caretIndex );730appendToBuffer( buffer, bufsize,731"\r\n Char count: %d",732textInfo.charCount );733}734if ( GetAccessibleTextSelectionInfo(vmID, ac, &textSelection) ) {735736appendToBuffer( buffer, bufsize,737"\r\n Selection start index: %d",738textSelection.selectionStartIndex );739appendToBuffer( buffer, bufsize,740"\r\n Selection end index: %d",741textSelection.selectionEndIndex );742appendToBuffer( buffer, bufsize,743"\r\n Selected text: %ls",744textSelection.selectedText );745}746747/* ===== AccessibleText information at the mouse point ===== */748749appendToBuffer( buffer, bufsize,750"\r\n\r\n At mouse point index: %d", textInfo.indexAtPoint);751752if (GetAccessibleTextRect(vmID, ac, &rectInfo, textInfo.indexAtPoint)) {753754appendToBuffer( buffer, bufsize,755"\r\n Character bounding rectangle: [%d, %d, %d, %d]",756rectInfo.x, rectInfo.y, rectInfo.width, rectInfo.height );757}758759if ( GetAccessibleTextLineBounds( vmID, ac, textInfo.indexAtPoint,760&start, &end ) ) {761if ( GetAccessibleTextRange( vmID, ac, start, end, tmpBuf,762(sizeof(tmpBuf) / sizeof(wchar_t)) ) ) {763appendToBuffer( buffer, bufsize,764"\r\n Line bounds: [%d, %d]", start, end);765}766}767if ( GetAccessibleTextItems( vmID, ac, &textItems,768textInfo.indexAtPoint ) ) {769770appendToBuffer( buffer, bufsize,771"\r\n Character: %lc", textItems.letter );772appendToBuffer( buffer, bufsize,773"\r\n Word: %ls", textItems.word );774appendToBuffer( buffer, bufsize,775"\r\n Sentence: %ls", textItems.sentence );776}777778/* ===== AccessibleText attributes ===== */779780if (GetAccessibleTextAttributes(vmID, ac,781textInfo.indexAtPoint,782&attributeInfo)) {783784appendToBuffer( buffer, bufsize, "\r\n Core attributes: %s",785attributeInfo.bold ? "bold" : "not bold" );786appendToBuffer( buffer, bufsize, ", %s",787attributeInfo.italic ? "italic" : "not italic" );788appendToBuffer( buffer, bufsize, ", %s",789attributeInfo.underline ? "underline" : "not underline" );790appendToBuffer( buffer, bufsize, ", %s",791attributeInfo.strikethrough ? "strikethrough" :792"not strikethrough" );793appendToBuffer( buffer, bufsize, ", %s",794attributeInfo.superscript ? "superscript" :795"not superscript" );796appendToBuffer( buffer, bufsize, ", %s",797attributeInfo.subscript ? "subscript" : "not subscript" );798799appendToBuffer( buffer, bufsize,800"\r\n Background color: %ls",801attributeInfo.backgroundColor );802appendToBuffer( buffer, bufsize,803"\r\n Foreground color: %ls",804attributeInfo.foregroundColor );805appendToBuffer( buffer, bufsize,806"\r\n Font family: %ls",807attributeInfo.fontFamily );808appendToBuffer( buffer, bufsize,809"\r\n Font size: %d",810attributeInfo.fontSize );811812appendToBuffer( buffer, bufsize,813"\r\n First line indent: %f",814attributeInfo.firstLineIndent );815appendToBuffer( buffer, bufsize,816"\r\n Left indent: %f",817attributeInfo.leftIndent );818appendToBuffer( buffer, bufsize,819"\r\n Right indent: %f",820attributeInfo.rightIndent );821appendToBuffer( buffer, bufsize,822"\r\n Line spacing: %f",823attributeInfo.lineSpacing );824appendToBuffer( buffer, bufsize,825"\r\n Space above: %f",826attributeInfo.spaceAbove );827appendToBuffer( buffer, bufsize,828"\r\n Space below: %f",829attributeInfo.spaceBelow );830831appendToBuffer( buffer, bufsize,832"\r\n Full attribute string: %ls",833attributeInfo.fullAttributesString );834835// get the attribute run length836short runLength = -1;837if ( getTextAttributesInRange( vmID, ac, textInfo.indexAtPoint,838textInfo.indexAtPoint + 100,839&attributeInfo, &runLength ) ) {840appendToBuffer( buffer, bufsize,841"\r\n Attribute run: %d", runLength );842} else {843appendToBuffer( buffer, bufsize,844"\r\n getTextAttributesInRangeFailed" );845}846}847848/* ===== AccessibleText information at the caret index ===== */849850appendToBuffer( buffer, bufsize,851"\r\n\r\n At caret index: %d", textInfo.caretIndex);852853if (getCaretLocation(vmID, ac, &rectInfo, textInfo.caretIndex)) {854appendToBuffer( buffer, bufsize,855"\r\n Caret bounding rectangle: [%d, %d, %d, %d]",856rectInfo.x, rectInfo.y, rectInfo.width, rectInfo.height );857}858859if (GetAccessibleTextRect(vmID, ac, &rectInfo, textInfo.caretIndex)) {860861appendToBuffer( buffer, bufsize,862"\r\n Character bounding rectangle: [%d, %d, %d, %d]",863rectInfo.x, rectInfo.y, rectInfo.width, rectInfo.height );864}865866if ( GetAccessibleTextLineBounds( vmID, ac, textInfo.caretIndex,867&start, &end ) ) {868if ( GetAccessibleTextRange( vmID, ac, start, end, tmpBuf,869(sizeof(tmpBuf) / sizeof(wchar_t)) ) ) {870871appendToBuffer( buffer, bufsize,872"\r\n Line bounds: [%d, %d]", start, end);873}874}875if (GetAccessibleTextItems(vmID, ac, &textItems, textInfo.caretIndex)) {876877appendToBuffer( buffer, bufsize,878"\r\n Character: %lc", textItems.letter );879appendToBuffer( buffer, bufsize,880"\r\n Word: %ls", textItems.word );881appendToBuffer( buffer, bufsize,882"\r\n Sentence: %ls", textItems.sentence );883}884885/* ===== AccessibleText attributes ===== */886887if (GetAccessibleTextAttributes(vmID, ac, textInfo.caretIndex, &attributeInfo)) {888889appendToBuffer( buffer, bufsize, "\r\n Core attributes: %s",890attributeInfo.bold ? "bold" : "not bold" );891appendToBuffer( buffer, bufsize, ", %s",892attributeInfo.italic ? "italic" : "not italic" );893appendToBuffer( buffer, bufsize, ", %s",894attributeInfo.underline ? "underline" : "not underline" );895appendToBuffer( buffer, bufsize, ", %s",896attributeInfo.strikethrough ? "strikethrough" :897"not strikethrough" );898appendToBuffer( buffer, bufsize, ", %s",899attributeInfo.superscript ? "superscript" :900"not superscript" );901appendToBuffer( buffer, bufsize, ", %s",902attributeInfo.subscript ? "subscript" : "not subscript");903904appendToBuffer( buffer, bufsize,905"\r\n Background color: %ls",906attributeInfo.backgroundColor );907appendToBuffer( buffer, bufsize,908"\r\n Foreground color: %ls",909attributeInfo.foregroundColor );910appendToBuffer( buffer, bufsize,911"\r\n Font family: %ls", attributeInfo.fontFamily );912appendToBuffer( buffer, bufsize,913"\r\n Font size: %d", attributeInfo.fontSize);914915916appendToBuffer( buffer, bufsize,917"\r\n First line indent: %f",918attributeInfo.firstLineIndent );919appendToBuffer( buffer, bufsize,920"\r\n Left indent: %f", attributeInfo.leftIndent );921appendToBuffer( buffer, bufsize,922"\r\n Right indent: %f", attributeInfo.rightIndent );923appendToBuffer( buffer, bufsize,924"\r\n Line spacing: %f", attributeInfo.lineSpacing );925appendToBuffer( buffer, bufsize,926"\r\n Space above: %f", attributeInfo.spaceAbove );927appendToBuffer( buffer, bufsize,928"\r\n Space below: %f", attributeInfo.spaceBelow );929appendToBuffer( buffer, bufsize,930"\r\n Full attribute string: %ls",931attributeInfo.fullAttributesString );932// get the attribute run length933short runLength = -1;934if ( getTextAttributesInRange( vmID, ac, textInfo.caretIndex,935textInfo.caretIndex + 100,936&attributeInfo, &runLength ) ) {937appendToBuffer( buffer, bufsize,938"\r\n Attribute run: %d", runLength);939} else {940appendToBuffer( buffer, bufsize,941"\r\n getTextAttributesInRangeFailed" );942}943}944}945}946return buffer;947}948949950