1/* 2 * Copyright (C) 2013 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR 20 * PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "AccessibleTextImpl.h" 28 29#include "WebKitDLL.h" 30#include "WebView.h" 31 32#include <WebCore/Document.h> 33#include <WebCore/Editor.h> 34#include <WebCore/Frame.h> 35#include <WebCore/FrameSelection.h> 36#include <WebCore/HTMLTextFormControlElement.h> 37#include <WebCore/Node.h> 38#include <WebCore/Page.h> 39#include <WebCore/Position.h> 40#include <WebCore/RenderTextControl.h> 41#include <WebCore/VisibleSelection.h> 42#include <WebCore/VisibleUnits.h> 43#include <WebCore/htmlediting.h> 44 45using namespace WebCore; 46 47AccessibleText::AccessibleText(WebCore::AccessibilityObject* obj, HWND window) 48 : AccessibleBase(obj, window) 49{ 50 ASSERT_ARG(obj, obj->isStaticText() || obj->isTextControl() || (obj->node() && obj->node()->isTextNode())); 51 ASSERT_ARG(obj, obj->isAccessibilityRenderObject()); 52} 53 54// IAccessibleText 55HRESULT AccessibleText::addSelection(long startOffset, long endOffset) 56{ 57 if (initialCheck() == E_POINTER) 58 return E_POINTER; 59 60 startOffset = convertSpecialOffset(startOffset); 61 endOffset = convertSpecialOffset(endOffset); 62 63 m_object->setSelectedTextRange(PlainTextRange(startOffset, endOffset-startOffset)); 64 65 return S_OK; 66} 67 68HRESULT AccessibleText::get_attributes(long offset, long* startOffset, long* endOffset, BSTR* textAttributes) 69{ 70 if (initialCheck() == E_POINTER) 71 return E_POINTER; 72 73 offset = convertSpecialOffset(offset); 74 75 return E_NOTIMPL; 76} 77 78HRESULT AccessibleText::get_caretOffset(long* offset) 79{ 80 if (initialCheck() == E_POINTER) 81 return E_POINTER; 82 83 VisiblePosition caretPosition = m_object->visiblePositionForPoint(m_object->document()->frame()->selection()->absoluteCaretBounds().center()); 84 85 int caretOffset = caretPosition.deepEquivalent().offsetInContainerNode(); 86 if (caretOffset < 0) 87 return E_FAIL; 88 *offset = caretOffset; 89 return S_OK; 90} 91 92HRESULT AccessibleText::get_characterExtents(long offset, enum IA2CoordinateType coordType, long* x, long* y, long* width, long* height) 93{ 94 if (initialCheck() == E_POINTER) 95 return E_POINTER; 96 97 offset = convertSpecialOffset(offset); 98 99 Node* node = m_object->node(); 100 if (!node) 101 return E_POINTER; 102 103 IntRect boundingRect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(VisiblePosition(Position(node, offset, Position::PositionIsOffsetInAnchor)), VisiblePosition(Position(node, offset+1, Position::PositionIsOffsetInAnchor)))); 104 *width = boundingRect.width(); 105 *height = boundingRect.height(); 106 switch (coordType) { 107 case IA2_COORDTYPE_SCREEN_RELATIVE: 108 POINT points[1]; 109 points[0].x = boundingRect.x(); 110 points[0].y = boundingRect.y(); 111 MapWindowPoints(m_window, 0, points, 1); 112 *x = points[0].x; 113 *y = points[0].y; 114 break; 115 case IA2_COORDTYPE_PARENT_RELATIVE: 116 *x = boundingRect.x(); 117 *y = boundingRect.y(); 118 break; 119 default: 120 return E_INVALIDARG; 121 } 122 123 return S_OK; 124} 125 126HRESULT AccessibleText::get_nSelections(long* nSelections) 127{ 128 if (initialCheck() == E_POINTER) 129 return E_POINTER; 130 131 if (m_object->document()->frame()->selection()->isNone()) 132 *nSelections = 0; 133 else 134 *nSelections = 1; 135 return S_OK; 136} 137 138HRESULT AccessibleText::get_offsetAtPoint(long x, long y, enum IA2CoordinateType coordType, long* offset) 139{ 140 if (initialCheck() == E_POINTER) 141 return E_POINTER; 142 143 Node* node = m_object->node(); 144 if (!node) 145 return E_POINTER; 146 147 VisiblePosition vpos; 148 switch (coordType) { 149 case IA2_COORDTYPE_SCREEN_RELATIVE: 150 POINT points[1]; 151 points[0].x = x; 152 points[0].y = y; 153 MapWindowPoints(0, m_window, points, 1); 154 vpos = m_object->visiblePositionForPoint(IntPoint(points[0].x, points[0].y)); 155 break; 156 case IA2_COORDTYPE_PARENT_RELATIVE: 157 vpos = m_object->visiblePositionForPoint(IntPoint(x, y)); 158 break; 159 default: 160 return E_INVALIDARG; 161 } 162 163 int caretPosition = vpos.deepEquivalent().offsetInContainerNode(); 164 if (caretPosition < 0 || caretPosition > m_object->stringValue().length()) 165 return S_FALSE; 166 return S_OK; 167} 168 169HRESULT AccessibleText::get_selection(long selectionIndex, long* startOffset, long* endOffset) 170{ 171 if (initialCheck() == E_POINTER) 172 return E_POINTER; 173 174 long selections; 175 get_nSelections(&selections); 176 if (selectionIndex < 0 || selectionIndex >= selections) 177 return E_INVALIDARG; 178 179 PlainTextRange selectionRange = m_object->selectedTextRange(); 180 181 *startOffset = selectionRange.start; 182 *endOffset = selectionRange.length; 183 return S_OK; 184} 185 186HRESULT AccessibleText::get_text(long startOffset, long endOffset, BSTR* text) 187{ 188 if (initialCheck() == E_POINTER) 189 return E_POINTER; 190 191 startOffset = convertSpecialOffset(startOffset); 192 endOffset = convertSpecialOffset(endOffset); 193 WTF::String substringText = m_object->stringValue().substring(startOffset, endOffset - startOffset); 194 195 *text = SysAllocStringLen(substringText.characters(), substringText.length()); 196 if (substringText.length() && !*text) 197 return E_OUTOFMEMORY; 198 199 return S_OK; 200} 201 202HRESULT AccessibleText::get_textBeforeOffset(long offset, enum IA2TextBoundaryType boundaryType, long* startOffset, long* endOffset, BSTR* text) 203{ 204 if (initialCheck() == E_POINTER) 205 return E_POINTER; 206 207 if (!startOffset || !endOffset || !text) 208 return E_POINTER; 209 210 offset = convertSpecialOffset(offset); 211 212 if (offset < 0 || offset > m_object->stringValue().length()) 213 return E_INVALIDARG; 214 215 // Obtain the desired text range 216 VisiblePosition currentPosition = m_object->visiblePositionForIndex(offset); 217 VisiblePositionRange textRange; 218 int previousPos = std::max(0, static_cast<int>(offset-1)); 219 switch (boundaryType) { 220 case IA2_TEXT_BOUNDARY_CHAR: 221 textRange = m_object->visiblePositionRangeForRange(PlainTextRange(previousPos, 1)); 222 break; 223 case IA2_TEXT_BOUNDARY_WORD: 224 textRange = m_object->positionOfLeftWord(currentPosition); 225 textRange = m_object->positionOfRightWord(leftWordPosition(textRange.start, true)); 226 break; 227 case IA2_TEXT_BOUNDARY_SENTENCE: 228 textRange.start = m_object->previousSentenceStartPosition(currentPosition); 229 textRange = m_object->sentenceForPosition(textRange.start); 230 if (isInRange(currentPosition, textRange)) 231 textRange = m_object->sentenceForPosition(m_object->previousSentenceStartPosition(textRange.start.previous())); 232 break; 233 case IA2_TEXT_BOUNDARY_PARAGRAPH: 234 textRange.start = m_object->previousParagraphStartPosition(currentPosition); 235 textRange = m_object->paragraphForPosition(textRange.start); 236 if (isInRange(currentPosition, textRange)) 237 textRange = m_object->paragraphForPosition(m_object->previousParagraphStartPosition(textRange.start.previous())); 238 break; 239 case IA2_TEXT_BOUNDARY_LINE: 240 textRange = m_object->visiblePositionRangeForLine(m_object->lineForPosition(currentPosition)); 241 textRange = m_object->leftLineVisiblePositionRange(textRange.start.previous()); 242 break; 243 case IA2_TEXT_BOUNDARY_ALL: 244 textRange = m_object->visiblePositionRangeForRange(PlainTextRange(0, offset)); 245 break; 246 default: 247 return E_INVALIDARG; 248 break; 249 } 250 251 // Obtain string and offsets associated with text range 252 *startOffset = textRange.start.deepEquivalent().offsetInContainerNode(); 253 *endOffset = textRange.end.deepEquivalent().offsetInContainerNode(); 254 255 if (*startOffset == *endOffset) 256 return S_FALSE; 257 258 WTF::String substringText = m_object->text().substring(*startOffset, *endOffset - *startOffset); 259 *text = SysAllocStringLen(substringText.characters(), substringText.length()); 260 261 if (substringText.length() && !*text) 262 return E_OUTOFMEMORY; 263 264 if (!*text) 265 return S_FALSE; 266 267 return S_OK; 268} 269 270HRESULT AccessibleText::get_textAfterOffset(long offset, enum IA2TextBoundaryType boundaryType, long* startOffset, long* endOffset, BSTR* text) 271{ 272 if (initialCheck() == E_POINTER) 273 return E_POINTER; 274 275 if (!startOffset || !endOffset || !text) 276 return E_POINTER; 277 278 int textLength = m_object->stringValue().length(); 279 offset = convertSpecialOffset(offset); 280 281 if (offset < 0 || offset > textLength) 282 return E_INVALIDARG; 283 284 VisiblePosition currentPosition = m_object->visiblePositionForIndex(offset); 285 VisiblePositionRange textRange; 286 287 // Obtain the desired text range 288 switch (boundaryType) { 289 case IA2_TEXT_BOUNDARY_CHAR: 290 textRange = m_object->visiblePositionRangeForRange(PlainTextRange(offset + 1, offset + 2)); 291 break; 292 case IA2_TEXT_BOUNDARY_WORD: 293 textRange = m_object->positionOfRightWord(rightWordPosition(currentPosition, true)); 294 break; 295 case IA2_TEXT_BOUNDARY_SENTENCE: 296 textRange.end = m_object->nextSentenceEndPosition(currentPosition); 297 textRange = m_object->sentenceForPosition(textRange.end); 298 if (isInRange(currentPosition, textRange)) 299 textRange = m_object->sentenceForPosition(m_object->nextSentenceEndPosition(textRange.end.next())); 300 break; 301 case IA2_TEXT_BOUNDARY_PARAGRAPH: 302 textRange.end = m_object->nextParagraphEndPosition(currentPosition); 303 textRange = m_object->paragraphForPosition(textRange.end); 304 if (isInRange(currentPosition, textRange)) 305 textRange = m_object->paragraphForPosition(m_object->nextParagraphEndPosition(textRange.end.next())); 306 break; 307 case IA2_TEXT_BOUNDARY_LINE: 308 textRange = m_object->visiblePositionRangeForLine(m_object->lineForPosition(currentPosition)); 309 textRange = m_object->rightLineVisiblePositionRange(textRange.end.next()); 310 break; 311 case IA2_TEXT_BOUNDARY_ALL: 312 textRange = m_object->visiblePositionRangeForRange(PlainTextRange(offset, textLength-offset)); 313 break; 314 default: 315 return E_INVALIDARG; 316 break; 317 } 318 319 // Obtain string and offsets associated with text range 320 *startOffset = textRange.start.deepEquivalent().offsetInContainerNode(); 321 *endOffset = textRange.end.deepEquivalent().offsetInContainerNode(); 322 323 if (*startOffset == *endOffset) 324 return S_FALSE; 325 326 WTF::String substringText = m_object->text().substring(*startOffset, *endOffset - *startOffset); 327 *text = SysAllocStringLen(substringText.characters(), substringText.length()); 328 if (substringText.length() && !*text) 329 return E_OUTOFMEMORY; 330 331 if (!*text) 332 return S_FALSE; 333 334 return S_OK; 335} 336 337HRESULT AccessibleText::get_textAtOffset(long offset, enum IA2TextBoundaryType boundaryType, long* startOffset, long* endOffset, BSTR* text) 338{ 339 if (initialCheck() == E_POINTER) 340 return E_POINTER; 341 342 if (!startOffset || !endOffset || !text) 343 return E_POINTER; 344 345 int textLength = m_object->stringValue().length(); 346 347 offset = convertSpecialOffset(offset); 348 349 if (offset < 0 || offset > textLength) 350 return E_INVALIDARG; 351 352 // Obtain the desired text range 353 VisiblePosition currentPosition = m_object->visiblePositionForIndex(offset); 354 VisiblePositionRange textRange; 355 switch (boundaryType) { 356 case IA2_TEXT_BOUNDARY_CHAR: 357 textRange = m_object->visiblePositionRangeForRange(PlainTextRange(offset, 1)); 358 break; 359 case IA2_TEXT_BOUNDARY_WORD: 360 textRange = m_object->positionOfRightWord(leftWordPosition(currentPosition.next(), true)); 361 break; 362 case IA2_TEXT_BOUNDARY_SENTENCE: 363 textRange = m_object->sentenceForPosition(currentPosition); 364 break; 365 case IA2_TEXT_BOUNDARY_PARAGRAPH: 366 textRange = m_object->paragraphForPosition(currentPosition); 367 break; 368 case IA2_TEXT_BOUNDARY_LINE: 369 textRange = m_object->leftLineVisiblePositionRange(currentPosition); 370 break; 371 case IA2_TEXT_BOUNDARY_ALL: 372 textRange = m_object->visiblePositionRangeForRange(PlainTextRange(0, m_object->text().length())); 373 break; 374 default: 375 return E_INVALIDARG; 376 break; 377 } 378 379 // Obtain string and offsets associated with text range 380 *startOffset = textRange.start.deepEquivalent().offsetInContainerNode(); 381 *endOffset = textRange.end.deepEquivalent().offsetInContainerNode(); 382 383 if (*startOffset == *endOffset) 384 return S_FALSE; 385 386 WTF::String substringText = m_object->text().substring(*startOffset, *endOffset - *startOffset); 387 *text = SysAllocStringLen(substringText.characters(), substringText.length()); 388 389 if (substringText.length() && !*text) 390 return E_OUTOFMEMORY; 391 392 if (!*text) 393 return S_FALSE; 394 395 return S_OK; 396} 397 398HRESULT AccessibleText::removeSelection(long selectionIndex) 399{ 400 if (initialCheck() == E_POINTER) 401 return E_POINTER; 402 403 long selections; 404 get_nSelections(&selections); 405 if (selectionIndex < 0 || selectionIndex >= selections) 406 return E_INVALIDARG; 407 408 m_object->document()->frame()->selection()->clear(); 409 return S_OK; 410} 411 412HRESULT AccessibleText::setCaretOffset(long offset) 413{ 414 if (initialCheck() == E_POINTER) 415 return E_POINTER; 416 417 offset = convertSpecialOffset(offset); 418 419 Node* node = m_object->node(); 420 if (!node) 421 return E_POINTER; 422 423 m_object->document()->frame()->selection()->setSelection(VisibleSelection(VisiblePosition(Position(node, offset, Position::PositionIsOffsetInAnchor)))); 424 return S_OK; 425} 426 427HRESULT AccessibleText::setSelection(long selectionIndex, long startOffset, long endOffset) 428{ 429 if (initialCheck() == E_POINTER) 430 return E_POINTER; 431 432 long selections; 433 get_nSelections(&selections); 434 if (selectionIndex < 0 || selectionIndex >= selections) 435 return E_INVALIDARG; 436 437 m_object->setSelectedTextRange(PlainTextRange(startOffset, endOffset - startOffset)); 438 return S_OK; 439} 440 441HRESULT AccessibleText::get_nCharacters(long* characters) 442{ 443 if (initialCheck() == E_POINTER) 444 return E_POINTER; 445 446 int length = m_object->stringValue().length(); 447 if (length < 0) 448 return E_FAIL; 449 450 *characters = length; 451 return S_OK; 452} 453 454HRESULT AccessibleText::scrollSubstringTo(long startIndex, long endIndex, enum IA2ScrollType scrollType) 455{ 456 if (initialCheck() == E_POINTER) 457 return E_POINTER; 458 459 startIndex = convertSpecialOffset(startIndex); 460 endIndex = convertSpecialOffset(endIndex); 461 462 VisiblePositionRange textRange = m_object->visiblePositionRangeForRange(PlainTextRange(startIndex, endIndex-startIndex)); 463 if (textRange.start.isNull() || textRange.end.isNull()) 464 return S_FALSE; 465 466 IntRect boundingBox = makeRange(textRange.start, textRange.end)->boundingBox(); 467 switch (scrollType) { 468 case IA2_SCROLL_TYPE_TOP_LEFT: 469 m_object->scrollToGlobalPoint(boundingBox.minXMinYCorner()); 470 break; 471 case IA2_SCROLL_TYPE_BOTTOM_RIGHT: 472 m_object->scrollToGlobalPoint(boundingBox.maxXMaxYCorner()); 473 break; 474 case IA2_SCROLL_TYPE_TOP_EDGE: 475 m_object->scrollToGlobalPoint(IntPoint((boundingBox.x() + boundingBox.maxX()) / 2, boundingBox.y())); 476 break; 477 case IA2_SCROLL_TYPE_BOTTOM_EDGE: 478 m_object->scrollToGlobalPoint(IntPoint((boundingBox.x() + boundingBox.maxX()) / 2, boundingBox.maxY())); 479 break; 480 case IA2_SCROLL_TYPE_LEFT_EDGE: 481 m_object->scrollToGlobalPoint(IntPoint(boundingBox.x(), (boundingBox.y() + boundingBox.maxY()) / 2)); 482 break; 483 case IA2_SCROLL_TYPE_RIGHT_EDGE: 484 m_object->scrollToGlobalPoint(IntPoint(boundingBox.maxX(), (boundingBox.y() + boundingBox.maxY()) / 2)); 485 break; 486 case IA2_SCROLL_TYPE_ANYWHERE: 487 m_object->scrollToGlobalPoint(boundingBox.center()); 488 break; 489 default: 490 return E_INVALIDARG; 491 } 492 return S_OK; 493} 494 495HRESULT AccessibleText::scrollSubstringToPoint(long startIndex, long endIndex, enum IA2CoordinateType coordinateType, long x, long y) 496{ 497 if (initialCheck() == E_POINTER) 498 return E_POINTER; 499 500 startIndex = convertSpecialOffset(startIndex); 501 endIndex = convertSpecialOffset(endIndex); 502 503 switch (coordinateType) { 504 case IA2_COORDTYPE_SCREEN_RELATIVE: 505 POINT points[1]; 506 points[0].x = x; 507 points[0].y = y; 508 MapWindowPoints(0, m_window, points, 1); 509 m_object->scrollToGlobalPoint(IntPoint(points[0].x, points[0].y)); 510 break; 511 case IA2_COORDTYPE_PARENT_RELATIVE: 512 m_object->scrollToGlobalPoint(IntPoint(x, y)); 513 break; 514 default: 515 return E_INVALIDARG; 516 } 517 518 return S_OK; 519} 520 521HRESULT AccessibleText::get_newText(IA2TextSegment* newText) 522{ 523 if (initialCheck() == E_POINTER) 524 return E_POINTER; 525 526 return E_NOTIMPL; 527} 528 529HRESULT AccessibleText::get_oldText(IA2TextSegment* oldText) 530{ 531 if (initialCheck() == E_POINTER) 532 return E_POINTER; 533 534 return E_NOTIMPL; 535} 536 537 538// IAccessibleText2 539HRESULT AccessibleText::get_attributeRange(long offset, BSTR filter, long* startOffset, long* endOffset, BSTR* attributeValues) 540{ 541 if (initialCheck() == E_POINTER) 542 return E_POINTER; 543 544 return E_NOTIMPL; 545} 546 547HRESULT AccessibleText::copyText(long startOffset, long endOffset) 548{ 549 if (initialCheck() == E_POINTER) 550 return E_POINTER; 551 552 startOffset = convertSpecialOffset(startOffset); 553 endOffset = convertSpecialOffset(endOffset); 554 555 Frame* frame = m_object->document()->frame(); 556 if (!frame) 557 return E_POINTER; 558 559 addSelection(startOffset, endOffset); 560 561 frame->editor().copy(); 562 return S_OK; 563} 564 565HRESULT AccessibleText::deleteText(long startOffset, long endOffset) 566{ 567 if (m_object->isReadOnly()) 568 return S_FALSE; 569 570 if (initialCheck() == E_POINTER) 571 return E_POINTER; 572 573 Frame* frame = m_object->document()->frame(); 574 if (!frame) 575 return E_POINTER; 576 577 addSelection(startOffset, endOffset); 578 579 frame->editor().deleteSelectionWithSmartDelete(false); 580 return S_OK; 581} 582 583HRESULT AccessibleText::insertText(long offset, BSTR* text) 584{ 585 if (m_object->isReadOnly()) 586 return S_FALSE; 587 588 if (initialCheck() == E_POINTER) 589 return E_POINTER; 590 591 offset = convertSpecialOffset(offset); 592 593 Frame* frame = m_object->document()->frame(); 594 if (!frame) 595 return E_POINTER; 596 597 addSelection(offset, offset); 598 599 frame->editor().insertText(*text, 0); 600 return S_OK; 601} 602 603HRESULT AccessibleText::cutText(long startOffset, long endOffset) 604{ 605 if (m_object->isReadOnly()) 606 return S_FALSE; 607 608 if (initialCheck() == E_POINTER) 609 return E_POINTER; 610 611 startOffset = convertSpecialOffset(startOffset); 612 endOffset = convertSpecialOffset(endOffset); 613 614 Frame* frame = m_object->document()->frame(); 615 if (!frame) 616 return E_POINTER; 617 618 addSelection(startOffset, endOffset); 619 620 frame->editor().cut(); 621 return S_OK; 622} 623 624HRESULT AccessibleText::pasteText(long offset) 625{ 626 if (m_object->isReadOnly()) 627 return S_FALSE; 628 629 if (initialCheck() == E_POINTER) 630 return E_POINTER; 631 632 offset = convertSpecialOffset(offset); 633 634 Frame* frame = m_object->document()->frame(); 635 if (!frame) 636 return E_POINTER; 637 638 addSelection(offset, offset); 639 640 frame->editor().paste(); 641 return S_OK; 642} 643 644HRESULT AccessibleText::replaceText(long startOffset, long endOffset, BSTR* text) 645{ 646 if (m_object->isReadOnly()) 647 return S_FALSE; 648 649 if (initialCheck() == E_POINTER) 650 return E_POINTER; 651 652 startOffset = convertSpecialOffset(startOffset); 653 endOffset = convertSpecialOffset(endOffset); 654 655 Frame* frame = m_object->document()->frame(); 656 if (!frame) 657 return E_POINTER; 658 659 addSelection(startOffset, endOffset); 660 661 frame->editor().replaceSelectionWithText(*text, true, false); 662 return S_OK; 663} 664 665HRESULT AccessibleText::setAttributes(long startOffset, long endOffset, BSTR* attributes) 666{ 667 if (initialCheck() == E_POINTER) 668 return E_POINTER; 669 670 return E_NOTIMPL; 671} 672 673// IAccessible2 674HRESULT AccessibleText::get_attributes(BSTR* attributes) 675{ 676 WTF::String text("text-model:a1"); 677 *attributes = SysAllocStringLen(text.characters(), text.length()); 678 return S_OK; 679} 680 681// IUnknown 682HRESULT STDMETHODCALLTYPE AccessibleText::QueryInterface(REFIID riid, void** ppvObject) 683{ 684 if (IsEqualGUID(riid, __uuidof(IAccessibleText))) 685 *ppvObject = static_cast<IAccessibleText*>(this); 686 else if (IsEqualGUID(riid, __uuidof(IAccessibleEditableText))) 687 *ppvObject = static_cast<IAccessibleEditableText*>(this); 688 else if (IsEqualGUID(riid, __uuidof(IAccessible))) 689 *ppvObject = static_cast<IAccessible*>(this); 690 else if (IsEqualGUID(riid, __uuidof(IDispatch))) 691 *ppvObject = static_cast<IAccessible*>(this); 692 else if (IsEqualGUID(riid, __uuidof(IUnknown))) 693 *ppvObject = static_cast<IAccessible*>(this); 694 else if (IsEqualGUID(riid, __uuidof(IAccessible2_2))) 695 *ppvObject = static_cast<IAccessible2_2*>(this); 696 else if (IsEqualGUID(riid, __uuidof(IAccessible2))) 697 *ppvObject = static_cast<IAccessible2*>(this); 698 else if (IsEqualGUID(riid, __uuidof(IAccessibleComparable))) 699 *ppvObject = static_cast<IAccessibleComparable*>(this); 700 else if (IsEqualGUID(riid, __uuidof(IServiceProvider))) 701 *ppvObject = static_cast<IServiceProvider*>(this); 702 else if (IsEqualGUID(riid, __uuidof(AccessibleBase))) 703 *ppvObject = static_cast<AccessibleBase*>(this); 704 else { 705 *ppvObject = 0; 706 return E_NOINTERFACE; 707 } 708 AddRef(); 709 return S_OK; 710} 711 712ULONG STDMETHODCALLTYPE AccessibleText::Release(void) 713{ 714 ASSERT(m_refCount > 0); 715 if (--m_refCount) 716 return m_refCount; 717 delete this; 718 return 0; 719} 720 721int AccessibleText::convertSpecialOffset(int offset) 722{ 723 ASSERT(m_object); 724 725 if (offset == IA2_TEXT_OFFSET_LENGTH) 726 return m_object->stringValue().length(); 727 if (offset == IA2_TEXT_OFFSET_CARET) { 728 long caretOffset; 729 get_caretOffset(&caretOffset); 730 return caretOffset; 731 } 732 return offset; 733} 734 735HRESULT AccessibleText::initialCheck() 736{ 737 if (!m_object) 738 return E_FAIL; 739 740 Document* document = m_object->document(); 741 if (!document) 742 return E_FAIL; 743 744 Frame* frame = document->frame(); 745 if (!frame) 746 return E_FAIL; 747 748 return S_OK; 749} 750 751bool AccessibleText::isInRange(VisiblePosition& current, VisiblePositionRange& wordRange) 752{ 753 ASSERT(wordRange.start.isNotNull()); 754 ASSERT(wordRange.end.isNotNull()); 755 return comparePositions(current.deepEquivalent(), wordRange.start) >= 0 && comparePositions(current.deepEquivalent(), wordRange.end) <= 0; 756} 757