123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* vim:expandtab:shiftwidth=2:tabstop=2:
- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "ia2AccessibleText.h"
- #include "Accessible2.h"
- #include "AccessibleText_i.c"
- #include "HyperTextAccessibleWrap.h"
- #include "HyperTextAccessible-inl.h"
- #include "ProxyWrappers.h"
- #include "mozilla/ClearOnShutdown.h"
- using namespace mozilla;
- using namespace mozilla::a11y;
- StaticRefPtr<HyperTextAccessibleWrap> ia2AccessibleText::sLastTextChangeAcc;
- StaticAutoPtr<nsString> ia2AccessibleText::sLastTextChangeString;
- uint32_t ia2AccessibleText::sLastTextChangeStart = 0;
- uint32_t ia2AccessibleText::sLastTextChangeEnd = 0;
- bool ia2AccessibleText::sLastTextChangeWasInsert = false;
- // IAccessibleText
- STDMETHODIMP
- ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
- {
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- return textAcc->AddToSelection(aStartOffset, aEndOffset) ?
- S_OK : E_INVALIDARG;
- }
- STDMETHODIMP
- ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset,
- long *aEndOffset, BSTR *aTextAttributes)
- {
- if (!aStartOffset || !aEndOffset || !aTextAttributes)
- return E_INVALIDARG;
- *aStartOffset = 0;
- *aEndOffset = 0;
- *aTextAttributes = nullptr;
- int32_t startOffset = 0, endOffset = 0;
- HRESULT hr;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct()) {
- return CO_E_OBJNOTCONNECTED;
- }
- nsCOMPtr<nsIPersistentProperties> attributes =
- textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset);
- hr = AccessibleWrap::ConvertToIA2Attributes(attributes, aTextAttributes);
- if (FAILED(hr))
- return hr;
- *aStartOffset = startOffset;
- *aEndOffset = endOffset;
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::get_caretOffset(long *aOffset)
- {
- if (!aOffset)
- return E_INVALIDARG;
- *aOffset = -1;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct()) {
- return CO_E_OBJNOTCONNECTED;
- }
- *aOffset = textAcc->CaretOffset();
- return *aOffset != -1 ? S_OK : S_FALSE;
- }
- STDMETHODIMP
- ia2AccessibleText::get_characterExtents(long aOffset,
- enum IA2CoordinateType aCoordType,
- long* aX, long* aY,
- long* aWidth, long* aHeight)
- {
- if (!aX || !aY || !aWidth || !aHeight)
- return E_INVALIDARG;
- *aX = *aY = *aWidth = *aHeight = 0;
- uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
- nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
- nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
- nsIntRect rect;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- rect = textAcc->CharBounds(aOffset, geckoCoordType);
- *aX = rect.x;
- *aY = rect.y;
- *aWidth = rect.width;
- *aHeight = rect.height;
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::get_nSelections(long* aNSelections)
- {
- if (!aNSelections)
- return E_INVALIDARG;
- *aNSelections = 0;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct()) {
- return CO_E_OBJNOTCONNECTED;
- }
- *aNSelections = textAcc->SelectionCount();
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::get_offsetAtPoint(long aX, long aY,
- enum IA2CoordinateType aCoordType,
- long* aOffset)
- {
- if (!aOffset)
- return E_INVALIDARG;
- *aOffset = 0;
- uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
- nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
- nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct()) {
- return CO_E_OBJNOTCONNECTED;
- }
- *aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType);
- return *aOffset == -1 ? S_FALSE : S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset,
- long* aEndOffset)
- {
- if (!aStartOffset || !aEndOffset)
- return E_INVALIDARG;
- *aStartOffset = *aEndOffset = 0;
- int32_t startOffset = 0, endOffset = 0;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct()) {
- return CO_E_OBJNOTCONNECTED;
- }
- if (!textAcc->SelectionBoundsAt(aSelectionIndex, &startOffset, &endOffset)) {
- return E_INVALIDARG;
- }
- *aStartOffset = startOffset;
- *aEndOffset = endOffset;
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR* aText)
- {
- if (!aText)
- return E_INVALIDARG;
- *aText = nullptr;
- nsAutoString text;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct()) {
- return CO_E_OBJNOTCONNECTED;
- }
- if (!textAcc->IsValidRange(aStartOffset, aEndOffset)) {
- return E_INVALIDARG;
- }
- textAcc->TextSubstring(aStartOffset, aEndOffset, text);
- if (text.IsEmpty())
- return S_FALSE;
- *aText = ::SysAllocStringLen(text.get(), text.Length());
- return *aText ? S_OK : E_OUTOFMEMORY;
- }
- STDMETHODIMP
- ia2AccessibleText::get_textBeforeOffset(long aOffset,
- enum IA2TextBoundaryType aBoundaryType,
- long* aStartOffset, long* aEndOffset,
- BSTR* aText)
- {
- if (!aStartOffset || !aEndOffset || !aText)
- return E_INVALIDARG;
- *aStartOffset = *aEndOffset = 0;
- *aText = nullptr;
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- if (!textAcc->IsValidOffset(aOffset))
- return E_INVALIDARG;
- nsAutoString text;
- int32_t startOffset = 0, endOffset = 0;
- if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
- startOffset = 0;
- endOffset = textAcc->CharacterCount();
- textAcc->TextSubstring(startOffset, endOffset, text);
- } else {
- AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
- if (boundaryType == -1)
- return S_FALSE;
- textAcc->TextBeforeOffset(aOffset, boundaryType, &startOffset, &endOffset, text);
- }
- *aStartOffset = startOffset;
- *aEndOffset = endOffset;
- if (text.IsEmpty())
- return S_FALSE;
- *aText = ::SysAllocStringLen(text.get(), text.Length());
- return *aText ? S_OK : E_OUTOFMEMORY;
- }
- STDMETHODIMP
- ia2AccessibleText::get_textAfterOffset(long aOffset,
- enum IA2TextBoundaryType aBoundaryType,
- long* aStartOffset, long* aEndOffset,
- BSTR* aText)
- {
- if (!aStartOffset || !aEndOffset || !aText)
- return E_INVALIDARG;
- *aStartOffset = 0;
- *aEndOffset = 0;
- *aText = nullptr;
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- if (!textAcc->IsValidOffset(aOffset))
- return E_INVALIDARG;
- nsAutoString text;
- int32_t startOffset = 0, endOffset = 0;
- if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
- startOffset = 0;
- endOffset = textAcc->CharacterCount();
- textAcc->TextSubstring(startOffset, endOffset, text);
- } else {
- AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
- if (boundaryType == -1)
- return S_FALSE;
- textAcc->TextAfterOffset(aOffset, boundaryType, &startOffset, &endOffset, text);
- }
- *aStartOffset = startOffset;
- *aEndOffset = endOffset;
- if (text.IsEmpty())
- return S_FALSE;
- *aText = ::SysAllocStringLen(text.get(), text.Length());
- return *aText ? S_OK : E_OUTOFMEMORY;
- }
- STDMETHODIMP
- ia2AccessibleText::get_textAtOffset(long aOffset,
- enum IA2TextBoundaryType aBoundaryType,
- long* aStartOffset, long* aEndOffset,
- BSTR* aText)
- {
- if (!aStartOffset || !aEndOffset || !aText)
- return E_INVALIDARG;
- *aStartOffset = *aEndOffset = 0;
- *aText = nullptr;
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- if (!textAcc->IsValidOffset(aOffset))
- return E_INVALIDARG;
- nsAutoString text;
- int32_t startOffset = 0, endOffset = 0;
- if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
- startOffset = 0;
- endOffset = textAcc->CharacterCount();
- textAcc->TextSubstring(startOffset, endOffset, text);
- } else {
- AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
- if (boundaryType == -1)
- return S_FALSE;
- textAcc->TextAtOffset(aOffset, boundaryType, &startOffset, &endOffset, text);
- }
- *aStartOffset = startOffset;
- *aEndOffset = endOffset;
- if (text.IsEmpty())
- return S_FALSE;
- *aText = ::SysAllocStringLen(text.get(), text.Length());
- return *aText ? S_OK : E_OUTOFMEMORY;
- }
- STDMETHODIMP
- ia2AccessibleText::removeSelection(long aSelectionIndex)
- {
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- return textAcc->RemoveFromSelection(aSelectionIndex) ?
- S_OK : E_INVALIDARG;
- }
- STDMETHODIMP
- ia2AccessibleText::setCaretOffset(long aOffset)
- {
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- if (!textAcc->IsValidOffset(aOffset))
- return E_INVALIDARG;
- textAcc->SetCaretOffset(aOffset);
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
- long aEndOffset)
- {
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- return textAcc->SetSelectionBoundsAt(aSelectionIndex, aStartOffset, aEndOffset) ?
- S_OK : E_INVALIDARG;
- }
- STDMETHODIMP
- ia2AccessibleText::get_nCharacters(long* aNCharacters)
- {
- if (!aNCharacters)
- return E_INVALIDARG;
- *aNCharacters = 0;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- *aNCharacters = textAcc->CharacterCount();
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
- enum IA2ScrollType aScrollType)
- {
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
- return E_INVALIDARG;
- textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
- enum IA2CoordinateType aCoordType,
- long aX, long aY)
- {
- uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
- nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
- nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
- MOZ_ASSERT(!HyperTextProxyFor(this));
- HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
- if (textAcc->IsDefunct())
- return CO_E_OBJNOTCONNECTED;
- if (!textAcc->IsValidRange(aStartIndex, aEndIndex))
- return E_INVALIDARG;
- textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
- geckoCoordType, aX, aY);
- return S_OK;
- }
- STDMETHODIMP
- ia2AccessibleText::get_newText(IA2TextSegment *aNewText)
- {
- return GetModifiedText(true, aNewText);
- }
- STDMETHODIMP
- ia2AccessibleText::get_oldText(IA2TextSegment *aOldText)
- {
- return GetModifiedText(false, aOldText);
- }
- // ia2AccessibleText
- HRESULT
- ia2AccessibleText::GetModifiedText(bool aGetInsertedText,
- IA2TextSegment *aText)
- {
- if (!aText)
- return E_INVALIDARG;
- if (!sLastTextChangeAcc)
- return S_OK;
- if (aGetInsertedText != sLastTextChangeWasInsert)
- return S_OK;
- if (sLastTextChangeAcc != this)
- return S_OK;
- aText->start = sLastTextChangeStart;
- aText->end = sLastTextChangeEnd;
- if (sLastTextChangeString->IsEmpty())
- return S_FALSE;
- aText->text = ::SysAllocStringLen(sLastTextChangeString->get(), sLastTextChangeString->Length());
- return aText->text ? S_OK : E_OUTOFMEMORY;
- }
- AccessibleTextBoundary
- ia2AccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
- {
- switch (aBoundaryType) {
- case IA2_TEXT_BOUNDARY_CHAR:
- return nsIAccessibleText::BOUNDARY_CHAR;
- case IA2_TEXT_BOUNDARY_WORD:
- return nsIAccessibleText::BOUNDARY_WORD_START;
- case IA2_TEXT_BOUNDARY_LINE:
- return nsIAccessibleText::BOUNDARY_LINE_START;
- //case IA2_TEXT_BOUNDARY_SENTENCE:
- //case IA2_TEXT_BOUNDARY_PARAGRAPH:
- // XXX: not implemented
- default:
- return -1;
- }
- }
- void
- ia2AccessibleText::InitTextChangeData()
- {
- ClearOnShutdown(&sLastTextChangeAcc);
- ClearOnShutdown(&sLastTextChangeString);
- }
- void
- ia2AccessibleText::UpdateTextChangeData(HyperTextAccessibleWrap* aAcc,
- bool aInsert, const nsString& aStr,
- int32_t aStart, uint32_t aLen)
- {
- if (!sLastTextChangeString)
- sLastTextChangeString = new nsString();
- sLastTextChangeAcc = aAcc;
- sLastTextChangeStart = aStart;
- sLastTextChangeEnd = aStart + aLen;
- sLastTextChangeWasInsert = aInsert;
- *sLastTextChangeString = aStr;
- }
|