1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/windows/ia2/ia2AccessibleText.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,535 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:expandtab:shiftwidth=2:tabstop=2: 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "ia2AccessibleText.h" 1.12 + 1.13 +#include "Accessible2.h" 1.14 +#include "AccessibleText_i.c" 1.15 + 1.16 +#include "HyperTextAccessibleWrap.h" 1.17 +#include "HyperTextAccessible-inl.h" 1.18 + 1.19 +using namespace mozilla::a11y; 1.20 + 1.21 +// IAccessibleText 1.22 + 1.23 +STDMETHODIMP 1.24 +ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset) 1.25 +{ 1.26 + A11Y_TRYBLOCK_BEGIN 1.27 + 1.28 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.29 + if (textAcc->IsDefunct()) 1.30 + return CO_E_OBJNOTCONNECTED; 1.31 + 1.32 + return textAcc->AddToSelection(aStartOffset, aEndOffset) ? 1.33 + S_OK : E_INVALIDARG; 1.34 + 1.35 + A11Y_TRYBLOCK_END 1.36 +} 1.37 + 1.38 +STDMETHODIMP 1.39 +ia2AccessibleText::get_attributes(long aOffset, long *aStartOffset, 1.40 + long *aEndOffset, BSTR *aTextAttributes) 1.41 +{ 1.42 + A11Y_TRYBLOCK_BEGIN 1.43 + 1.44 + if (!aStartOffset || !aEndOffset || !aTextAttributes) 1.45 + return E_INVALIDARG; 1.46 + 1.47 + *aStartOffset = 0; 1.48 + *aEndOffset = 0; 1.49 + *aTextAttributes = nullptr; 1.50 + 1.51 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.52 + if (textAcc->IsDefunct()) 1.53 + return CO_E_OBJNOTCONNECTED; 1.54 + 1.55 + int32_t startOffset = 0, endOffset = 0; 1.56 + nsCOMPtr<nsIPersistentProperties> attributes = 1.57 + textAcc->TextAttributes(true, aOffset, &startOffset, &endOffset); 1.58 + 1.59 + HRESULT hr = AccessibleWrap::ConvertToIA2Attributes(attributes, 1.60 + aTextAttributes); 1.61 + if (FAILED(hr)) 1.62 + return hr; 1.63 + 1.64 + *aStartOffset = startOffset; 1.65 + *aEndOffset = endOffset; 1.66 + 1.67 + return S_OK; 1.68 + 1.69 + A11Y_TRYBLOCK_END 1.70 +} 1.71 + 1.72 +STDMETHODIMP 1.73 +ia2AccessibleText::get_caretOffset(long *aOffset) 1.74 +{ 1.75 + A11Y_TRYBLOCK_BEGIN 1.76 + 1.77 + if (!aOffset) 1.78 + return E_INVALIDARG; 1.79 + 1.80 + *aOffset = -1; 1.81 + 1.82 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.83 + if (textAcc->IsDefunct()) 1.84 + return CO_E_OBJNOTCONNECTED; 1.85 + 1.86 + *aOffset = textAcc->CaretOffset(); 1.87 + return *aOffset != -1 ? S_OK : S_FALSE; 1.88 + 1.89 + A11Y_TRYBLOCK_END 1.90 +} 1.91 + 1.92 +STDMETHODIMP 1.93 +ia2AccessibleText::get_characterExtents(long aOffset, 1.94 + enum IA2CoordinateType aCoordType, 1.95 + long* aX, long* aY, 1.96 + long* aWidth, long* aHeight) 1.97 +{ 1.98 + A11Y_TRYBLOCK_BEGIN 1.99 + 1.100 + if (!aX || !aY || !aWidth || !aHeight) 1.101 + return E_INVALIDARG; 1.102 + *aX = *aY = *aWidth = *aHeight = 0; 1.103 + 1.104 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.105 + if (textAcc->IsDefunct()) 1.106 + return CO_E_OBJNOTCONNECTED; 1.107 + 1.108 + uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ? 1.109 + nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE : 1.110 + nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE; 1.111 + 1.112 + nsIntRect rect = textAcc->CharBounds(aOffset, geckoCoordType); 1.113 + 1.114 + *aX = rect.x; 1.115 + *aY = rect.y; 1.116 + *aWidth = rect.width; 1.117 + *aHeight = rect.height; 1.118 + return S_OK; 1.119 + 1.120 + A11Y_TRYBLOCK_END 1.121 +} 1.122 + 1.123 +STDMETHODIMP 1.124 +ia2AccessibleText::get_nSelections(long* aNSelections) 1.125 +{ 1.126 + A11Y_TRYBLOCK_BEGIN 1.127 + 1.128 + if (!aNSelections) 1.129 + return E_INVALIDARG; 1.130 + *aNSelections = 0; 1.131 + 1.132 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.133 + if (textAcc->IsDefunct()) 1.134 + return CO_E_OBJNOTCONNECTED; 1.135 + 1.136 + *aNSelections = textAcc->SelectionCount(); 1.137 + return S_OK; 1.138 + 1.139 + A11Y_TRYBLOCK_END 1.140 +} 1.141 + 1.142 +STDMETHODIMP 1.143 +ia2AccessibleText::get_offsetAtPoint(long aX, long aY, 1.144 + enum IA2CoordinateType aCoordType, 1.145 + long* aOffset) 1.146 +{ 1.147 + A11Y_TRYBLOCK_BEGIN 1.148 + 1.149 + if (!aOffset) 1.150 + return E_INVALIDARG; 1.151 + *aOffset = 0; 1.152 + 1.153 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.154 + if (textAcc->IsDefunct()) 1.155 + return CO_E_OBJNOTCONNECTED; 1.156 + 1.157 + uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ? 1.158 + nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE : 1.159 + nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE; 1.160 + 1.161 + *aOffset = textAcc->OffsetAtPoint(aX, aY, geckoCoordType); 1.162 + return *aOffset == -1 ? S_FALSE : S_OK; 1.163 + 1.164 + A11Y_TRYBLOCK_END 1.165 +} 1.166 + 1.167 +STDMETHODIMP 1.168 +ia2AccessibleText::get_selection(long aSelectionIndex, long* aStartOffset, 1.169 + long* aEndOffset) 1.170 +{ 1.171 + A11Y_TRYBLOCK_BEGIN 1.172 + 1.173 + if (!aStartOffset || !aEndOffset) 1.174 + return E_INVALIDARG; 1.175 + *aStartOffset = *aEndOffset = 0; 1.176 + 1.177 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.178 + if (textAcc->IsDefunct()) 1.179 + return CO_E_OBJNOTCONNECTED; 1.180 + 1.181 + int32_t startOffset = 0, endOffset = 0; 1.182 + if (!textAcc->SelectionBoundsAt(aSelectionIndex, &startOffset, &endOffset)) 1.183 + return E_INVALIDARG; 1.184 + 1.185 + *aStartOffset = startOffset; 1.186 + *aEndOffset = endOffset; 1.187 + return S_OK; 1.188 + 1.189 + A11Y_TRYBLOCK_END 1.190 +} 1.191 + 1.192 +STDMETHODIMP 1.193 +ia2AccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR* aText) 1.194 +{ 1.195 + A11Y_TRYBLOCK_BEGIN 1.196 + 1.197 + if (!aText) 1.198 + return E_INVALIDARG; 1.199 + 1.200 + *aText = nullptr; 1.201 + 1.202 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.203 + if (textAcc->IsDefunct()) 1.204 + return CO_E_OBJNOTCONNECTED; 1.205 + 1.206 + if (!textAcc->IsValidRange(aStartOffset, aEndOffset)) 1.207 + return E_INVALIDARG; 1.208 + 1.209 + nsAutoString text; 1.210 + textAcc->TextSubstring(aStartOffset, aEndOffset, text); 1.211 + if (text.IsEmpty()) 1.212 + return S_FALSE; 1.213 + 1.214 + *aText = ::SysAllocStringLen(text.get(), text.Length()); 1.215 + return *aText ? S_OK : E_OUTOFMEMORY; 1.216 + 1.217 + A11Y_TRYBLOCK_END 1.218 +} 1.219 + 1.220 +STDMETHODIMP 1.221 +ia2AccessibleText::get_textBeforeOffset(long aOffset, 1.222 + enum IA2TextBoundaryType aBoundaryType, 1.223 + long* aStartOffset, long* aEndOffset, 1.224 + BSTR* aText) 1.225 +{ 1.226 + A11Y_TRYBLOCK_BEGIN 1.227 + 1.228 + if (!aStartOffset || !aEndOffset || !aText) 1.229 + return E_INVALIDARG; 1.230 + 1.231 + *aStartOffset = *aEndOffset = 0; 1.232 + *aText = nullptr; 1.233 + 1.234 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.235 + if (textAcc->IsDefunct()) 1.236 + return CO_E_OBJNOTCONNECTED; 1.237 + 1.238 + if (!textAcc->IsValidOffset(aOffset)) 1.239 + return E_INVALIDARG; 1.240 + 1.241 + nsAutoString text; 1.242 + int32_t startOffset = 0, endOffset = 0; 1.243 + 1.244 + if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) { 1.245 + startOffset = 0; 1.246 + endOffset = textAcc->CharacterCount(); 1.247 + textAcc->TextSubstring(startOffset, endOffset, text); 1.248 + } else { 1.249 + AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType); 1.250 + if (boundaryType == -1) 1.251 + return S_FALSE; 1.252 + 1.253 + textAcc->TextBeforeOffset(aOffset, boundaryType, &startOffset, &endOffset, text); 1.254 + } 1.255 + 1.256 + *aStartOffset = startOffset; 1.257 + *aEndOffset = endOffset; 1.258 + 1.259 + if (text.IsEmpty()) 1.260 + return S_FALSE; 1.261 + 1.262 + *aText = ::SysAllocStringLen(text.get(), text.Length()); 1.263 + return *aText ? S_OK : E_OUTOFMEMORY; 1.264 + 1.265 + A11Y_TRYBLOCK_END 1.266 +} 1.267 + 1.268 +STDMETHODIMP 1.269 +ia2AccessibleText::get_textAfterOffset(long aOffset, 1.270 + enum IA2TextBoundaryType aBoundaryType, 1.271 + long* aStartOffset, long* aEndOffset, 1.272 + BSTR* aText) 1.273 +{ 1.274 + A11Y_TRYBLOCK_BEGIN 1.275 + 1.276 + if (!aStartOffset || !aEndOffset || !aText) 1.277 + return E_INVALIDARG; 1.278 + 1.279 + *aStartOffset = 0; 1.280 + *aEndOffset = 0; 1.281 + *aText = nullptr; 1.282 + 1.283 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.284 + if (textAcc->IsDefunct()) 1.285 + return CO_E_OBJNOTCONNECTED; 1.286 + 1.287 + if (!textAcc->IsValidOffset(aOffset)) 1.288 + return E_INVALIDARG; 1.289 + 1.290 + nsAutoString text; 1.291 + int32_t startOffset = 0, endOffset = 0; 1.292 + 1.293 + if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) { 1.294 + startOffset = 0; 1.295 + endOffset = textAcc->CharacterCount(); 1.296 + textAcc->TextSubstring(startOffset, endOffset, text); 1.297 + } else { 1.298 + AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType); 1.299 + if (boundaryType == -1) 1.300 + return S_FALSE; 1.301 + textAcc->TextAfterOffset(aOffset, boundaryType, &startOffset, &endOffset, text); 1.302 + } 1.303 + 1.304 + *aStartOffset = startOffset; 1.305 + *aEndOffset = endOffset; 1.306 + 1.307 + if (text.IsEmpty()) 1.308 + return S_FALSE; 1.309 + 1.310 + *aText = ::SysAllocStringLen(text.get(), text.Length()); 1.311 + return *aText ? S_OK : E_OUTOFMEMORY; 1.312 + 1.313 + A11Y_TRYBLOCK_END 1.314 +} 1.315 + 1.316 +STDMETHODIMP 1.317 +ia2AccessibleText::get_textAtOffset(long aOffset, 1.318 + enum IA2TextBoundaryType aBoundaryType, 1.319 + long* aStartOffset, long* aEndOffset, 1.320 + BSTR* aText) 1.321 +{ 1.322 + A11Y_TRYBLOCK_BEGIN 1.323 + 1.324 + if (!aStartOffset || !aEndOffset || !aText) 1.325 + return E_INVALIDARG; 1.326 + 1.327 + *aStartOffset = *aEndOffset = 0; 1.328 + *aText = nullptr; 1.329 + 1.330 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.331 + if (textAcc->IsDefunct()) 1.332 + return CO_E_OBJNOTCONNECTED; 1.333 + 1.334 + if (!textAcc->IsValidOffset(aOffset)) 1.335 + return E_INVALIDARG; 1.336 + 1.337 + nsAutoString text; 1.338 + int32_t startOffset = 0, endOffset = 0; 1.339 + if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) { 1.340 + startOffset = 0; 1.341 + endOffset = textAcc->CharacterCount(); 1.342 + textAcc->TextSubstring(startOffset, endOffset, text); 1.343 + } else { 1.344 + AccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType); 1.345 + if (boundaryType == -1) 1.346 + return S_FALSE; 1.347 + textAcc->TextAtOffset(aOffset, boundaryType, &startOffset, &endOffset, text); 1.348 + } 1.349 + 1.350 + *aStartOffset = startOffset; 1.351 + *aEndOffset = endOffset; 1.352 + 1.353 + if (text.IsEmpty()) 1.354 + return S_FALSE; 1.355 + 1.356 + *aText = ::SysAllocStringLen(text.get(), text.Length()); 1.357 + return *aText ? S_OK : E_OUTOFMEMORY; 1.358 + 1.359 + A11Y_TRYBLOCK_END 1.360 +} 1.361 + 1.362 +STDMETHODIMP 1.363 +ia2AccessibleText::removeSelection(long aSelectionIndex) 1.364 +{ 1.365 + A11Y_TRYBLOCK_BEGIN 1.366 + 1.367 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.368 + if (textAcc->IsDefunct()) 1.369 + return CO_E_OBJNOTCONNECTED; 1.370 + 1.371 + return textAcc->RemoveFromSelection(aSelectionIndex) ? 1.372 + S_OK : E_INVALIDARG; 1.373 + 1.374 + A11Y_TRYBLOCK_END 1.375 +} 1.376 + 1.377 +STDMETHODIMP 1.378 +ia2AccessibleText::setCaretOffset(long aOffset) 1.379 +{ 1.380 + A11Y_TRYBLOCK_BEGIN 1.381 + 1.382 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.383 + if (textAcc->IsDefunct()) 1.384 + return CO_E_OBJNOTCONNECTED; 1.385 + 1.386 + if (!textAcc->IsValidOffset(aOffset)) 1.387 + return E_INVALIDARG; 1.388 + 1.389 + textAcc->SetCaretOffset(aOffset); 1.390 + return S_OK; 1.391 + 1.392 + A11Y_TRYBLOCK_END 1.393 +} 1.394 + 1.395 +STDMETHODIMP 1.396 +ia2AccessibleText::setSelection(long aSelectionIndex, long aStartOffset, 1.397 + long aEndOffset) 1.398 +{ 1.399 + A11Y_TRYBLOCK_BEGIN 1.400 + 1.401 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.402 + if (textAcc->IsDefunct()) 1.403 + return CO_E_OBJNOTCONNECTED; 1.404 + 1.405 + return textAcc->SetSelectionBoundsAt(aSelectionIndex, aStartOffset, aEndOffset) ? 1.406 + S_OK : E_INVALIDARG; 1.407 + 1.408 + A11Y_TRYBLOCK_END 1.409 +} 1.410 + 1.411 +STDMETHODIMP 1.412 +ia2AccessibleText::get_nCharacters(long* aNCharacters) 1.413 +{ 1.414 + A11Y_TRYBLOCK_BEGIN 1.415 + 1.416 + if (!aNCharacters) 1.417 + return E_INVALIDARG; 1.418 + *aNCharacters = 0; 1.419 + 1.420 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.421 + if (textAcc->IsDefunct()) 1.422 + return CO_E_OBJNOTCONNECTED; 1.423 + 1.424 + *aNCharacters = textAcc->CharacterCount(); 1.425 + return S_OK; 1.426 + 1.427 + A11Y_TRYBLOCK_END 1.428 +} 1.429 + 1.430 +STDMETHODIMP 1.431 +ia2AccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex, 1.432 + enum IA2ScrollType aScrollType) 1.433 +{ 1.434 + A11Y_TRYBLOCK_BEGIN 1.435 + 1.436 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.437 + if (textAcc->IsDefunct()) 1.438 + return CO_E_OBJNOTCONNECTED; 1.439 + 1.440 + if (!textAcc->IsValidRange(aStartIndex, aEndIndex)) 1.441 + return E_INVALIDARG; 1.442 + 1.443 + textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType); 1.444 + return S_OK; 1.445 + 1.446 + A11Y_TRYBLOCK_END 1.447 +} 1.448 + 1.449 +STDMETHODIMP 1.450 +ia2AccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex, 1.451 + enum IA2CoordinateType aCoordType, 1.452 + long aX, long aY) 1.453 +{ 1.454 + A11Y_TRYBLOCK_BEGIN 1.455 + 1.456 + HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this); 1.457 + if (textAcc->IsDefunct()) 1.458 + return CO_E_OBJNOTCONNECTED; 1.459 + 1.460 + if (!textAcc->IsValidRange(aStartIndex, aEndIndex)) 1.461 + return E_INVALIDARG; 1.462 + 1.463 + uint32_t geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ? 1.464 + nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE : 1.465 + nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE; 1.466 + 1.467 + textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex, 1.468 + geckoCoordType, aX, aY); 1.469 + return S_OK; 1.470 + 1.471 + A11Y_TRYBLOCK_END 1.472 +} 1.473 + 1.474 +STDMETHODIMP 1.475 +ia2AccessibleText::get_newText(IA2TextSegment *aNewText) 1.476 +{ 1.477 + A11Y_TRYBLOCK_BEGIN 1.478 + 1.479 + return GetModifiedText(true, aNewText); 1.480 + 1.481 + A11Y_TRYBLOCK_END 1.482 +} 1.483 + 1.484 +STDMETHODIMP 1.485 +ia2AccessibleText::get_oldText(IA2TextSegment *aOldText) 1.486 +{ 1.487 + A11Y_TRYBLOCK_BEGIN 1.488 + 1.489 + return GetModifiedText(false, aOldText); 1.490 + 1.491 + A11Y_TRYBLOCK_END 1.492 +} 1.493 + 1.494 +// ia2AccessibleText 1.495 + 1.496 +HRESULT 1.497 +ia2AccessibleText::GetModifiedText(bool aGetInsertedText, 1.498 + IA2TextSegment *aText) 1.499 +{ 1.500 + if (!aText) 1.501 + return E_INVALIDARG; 1.502 + 1.503 + uint32_t startOffset = 0, endOffset = 0; 1.504 + nsAutoString text; 1.505 + 1.506 + nsresult rv = GetModifiedText(aGetInsertedText, text, 1.507 + &startOffset, &endOffset); 1.508 + if (NS_FAILED(rv)) 1.509 + return GetHRESULT(rv); 1.510 + 1.511 + aText->start = startOffset; 1.512 + aText->end = endOffset; 1.513 + 1.514 + if (text.IsEmpty()) 1.515 + return S_FALSE; 1.516 + 1.517 + aText->text = ::SysAllocStringLen(text.get(), text.Length()); 1.518 + return aText->text ? S_OK : E_OUTOFMEMORY; 1.519 +} 1.520 + 1.521 +AccessibleTextBoundary 1.522 +ia2AccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType) 1.523 +{ 1.524 + switch (aBoundaryType) { 1.525 + case IA2_TEXT_BOUNDARY_CHAR: 1.526 + return nsIAccessibleText::BOUNDARY_CHAR; 1.527 + case IA2_TEXT_BOUNDARY_WORD: 1.528 + return nsIAccessibleText::BOUNDARY_WORD_START; 1.529 + case IA2_TEXT_BOUNDARY_LINE: 1.530 + return nsIAccessibleText::BOUNDARY_LINE_START; 1.531 + //case IA2_TEXT_BOUNDARY_SENTENCE: 1.532 + //case IA2_TEXT_BOUNDARY_PARAGRAPH: 1.533 + // XXX: not implemented 1.534 + default: 1.535 + return -1; 1.536 + } 1.537 +} 1.538 +