Bug 453883, ensure true/false marcos are available, r=joshmoz, sr=jst
[wine-gecko.git] / accessible / src / msaa / CAccessibleText.cpp
blob4f6852fa1cddc619b9c24fac045bc37183d8d632
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
17 * The Original Code is mozilla.org code.
19 * The Initial Developer of the Original Code is
20 * Mozilla Foundation.
21 * Portions created by the Initial Developer are Copyright (C) 2007
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
25 * Alexander Surkov <surkov.alexander@gmail.com> (original author)
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "CAccessibleText.h"
43 #include "Accessible2.h"
44 #include "AccessibleText_i.c"
46 #include "nsIAccessible.h"
47 #include "nsIAccessibleText.h"
48 #include "nsIAccessibleTypes.h"
49 #include "nsIWinAccessNode.h"
50 #include "nsAccessNodeWrap.h"
51 #include "nsAccessibleWrap.h"
53 #include "nsCOMPtr.h"
54 #include "nsString.h"
56 #define GET_NSIACCESSIBLETEXT \
57 nsCOMPtr<nsIAccessibleText> textAcc(do_QueryInterface(this));\
58 NS_ASSERTION(textAcc,\
59 "Subclass of CAccessibleText doesn't implement nsIAccessibleText");\
60 if (!textAcc)\
61 return E_FAIL;\
63 // IUnknown
65 STDMETHODIMP
66 CAccessibleText::QueryInterface(REFIID iid, void** ppv)
68 *ppv = NULL;
70 if (IID_IAccessibleText == iid) {
71 nsCOMPtr<nsIAccessibleText> textAcc(do_QueryInterface(this));
72 if (!textAcc) {
73 return E_NOINTERFACE;
75 *ppv = static_cast<IAccessibleText*>(this);
76 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
77 return S_OK;
80 return E_NOINTERFACE;
83 // IAccessibleText
85 STDMETHODIMP
86 CAccessibleText::addSelection(long aStartOffset, long aEndOffset)
88 __try {
89 GET_NSIACCESSIBLETEXT
91 nsresult rv = textAcc->AddSelection(aStartOffset, aEndOffset);
92 return GetHRESULT(rv);
94 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
95 return E_FAIL;
98 STDMETHODIMP
99 CAccessibleText::get_attributes(long aOffset, long *aStartOffset,
100 long *aEndOffset, BSTR *aTextAttributes)
102 __try {
103 if (!aStartOffset || !aEndOffset || !aTextAttributes)
104 return E_INVALIDARG;
106 *aStartOffset = 0;
107 *aEndOffset = 0;
108 *aTextAttributes = NULL;
110 GET_NSIACCESSIBLETEXT
112 PRInt32 startOffset = 0, endOffset = 0;
113 nsCOMPtr<nsIPersistentProperties> attributes;
114 nsresult rv = textAcc->GetTextAttributes(PR_TRUE, aOffset,
115 &startOffset, &endOffset,
116 getter_AddRefs(attributes));
117 if (NS_FAILED(rv))
118 return GetHRESULT(rv);
120 HRESULT hr = nsAccessibleWrap::ConvertToIA2Attributes(attributes,
121 aTextAttributes);
122 if (FAILED(hr))
123 return hr;
125 *aStartOffset = startOffset;
126 *aEndOffset = endOffset;
128 return S_OK;
130 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
131 return E_FAIL;
134 STDMETHODIMP
135 CAccessibleText::get_caretOffset(long *aOffset)
137 __try {
138 *aOffset = -1;
140 GET_NSIACCESSIBLETEXT
142 PRInt32 offset = 0;
143 nsresult rv = textAcc->GetCaretOffset(&offset);
144 if (NS_FAILED(rv))
145 return GetHRESULT(rv);
147 *aOffset = offset;
148 return S_OK;
150 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
151 return E_FAIL;
154 STDMETHODIMP
155 CAccessibleText::get_characterExtents(long aOffset,
156 enum IA2CoordinateType aCoordType,
157 long *aX, long *aY,
158 long *aWidth, long *aHeight)
160 __try {
161 *aX = 0;
162 *aY = 0;
163 *aWidth = 0;
164 *aHeight = 0;
166 GET_NSIACCESSIBLETEXT
168 PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
169 nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
170 nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
172 PRInt32 x = 0, y =0, width = 0, height = 0;
173 nsresult rv = textAcc->GetCharacterExtents (aOffset, &x, &y, &width, &height,
174 geckoCoordType);
175 if (NS_FAILED(rv))
176 return GetHRESULT(rv);
178 *aX = x;
179 *aY = y;
180 *aWidth = width;
181 *aHeight = height;
182 return S_OK;
184 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
185 return E_FAIL;
188 STDMETHODIMP
189 CAccessibleText::get_nSelections(long *aNSelections)
191 __try {
192 *aNSelections = 0;
194 GET_NSIACCESSIBLETEXT
196 PRInt32 selCount = 0;
197 nsresult rv = textAcc->GetSelectionCount(&selCount);
198 if (NS_FAILED(rv))
199 return GetHRESULT(rv);
201 *aNSelections = selCount;
202 return S_OK;
204 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
205 return E_FAIL;
208 STDMETHODIMP
209 CAccessibleText::get_offsetAtPoint(long aX, long aY,
210 enum IA2CoordinateType aCoordType,
211 long *aOffset)
213 __try {
214 *aOffset = 0;
216 GET_NSIACCESSIBLETEXT
218 PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
219 nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
220 nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
222 PRInt32 offset = 0;
223 nsresult rv = textAcc->GetOffsetAtPoint(aX, aY, geckoCoordType, &offset);
224 if (NS_FAILED(rv))
225 return GetHRESULT(rv);
227 *aOffset = offset;
228 return S_OK;
230 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
231 return E_FAIL;
234 STDMETHODIMP
235 CAccessibleText::get_selection(long aSelectionIndex, long *aStartOffset,
236 long *aEndOffset)
238 __try {
239 *aStartOffset = 0;
240 *aEndOffset = 0;
242 GET_NSIACCESSIBLETEXT
244 PRInt32 startOffset = 0, endOffset = 0;
245 nsresult rv = textAcc->GetSelectionBounds(aSelectionIndex,
246 &startOffset, &endOffset);
247 if (NS_FAILED(rv))
248 return GetHRESULT(rv);
250 *aStartOffset = startOffset;
251 *aEndOffset = endOffset;
252 return S_OK;
254 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
255 return E_FAIL;
258 STDMETHODIMP
259 CAccessibleText::get_text(long aStartOffset, long aEndOffset, BSTR *aText)
261 __try {
262 *aText = NULL;
264 GET_NSIACCESSIBLETEXT
266 nsAutoString text;
267 nsresult rv = textAcc->GetText(aStartOffset, aEndOffset, text);
268 if (NS_FAILED(rv))
269 return GetHRESULT(rv);
271 if (text.IsEmpty())
272 return S_FALSE;
274 *aText = ::SysAllocStringLen(text.get(), text.Length());
275 return *aText ? S_OK : E_OUTOFMEMORY;
277 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
278 return E_FAIL;
281 STDMETHODIMP
282 CAccessibleText::get_textBeforeOffset(long aOffset,
283 enum IA2TextBoundaryType aBoundaryType,
284 long *aStartOffset, long *aEndOffset,
285 BSTR *aText)
287 __try {
288 *aStartOffset = 0;
289 *aEndOffset = 0;
290 *aText = NULL;
292 GET_NSIACCESSIBLETEXT
294 nsresult rv = NS_OK;
295 nsAutoString text;
296 PRInt32 startOffset = 0, endOffset = 0;
298 if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
299 startOffset = 0;
300 textAcc->GetCharacterCount(&endOffset);
301 rv = textAcc->GetText(startOffset, endOffset, text);
302 } else {
303 nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
304 if (boundaryType == -1)
305 return S_FALSE;
306 rv = textAcc->GetTextBeforeOffset(aOffset, boundaryType,
307 &startOffset, &endOffset, text);
310 if (NS_FAILED(rv))
311 return GetHRESULT(rv);
313 *aStartOffset = startOffset;
314 *aEndOffset = endOffset;
316 if (text.IsEmpty())
317 return S_FALSE;
319 *aText = ::SysAllocStringLen(text.get(), text.Length());
320 return *aText ? S_OK : E_OUTOFMEMORY;
322 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
323 return E_FAIL;
326 STDMETHODIMP
327 CAccessibleText::get_textAfterOffset(long aOffset,
328 enum IA2TextBoundaryType aBoundaryType,
329 long *aStartOffset, long *aEndOffset,
330 BSTR *aText)
332 __try {
333 *aStartOffset = 0;
334 *aEndOffset = 0;
335 *aText = NULL;
337 GET_NSIACCESSIBLETEXT
339 nsresult rv = NS_OK;
340 nsAutoString text;
341 PRInt32 startOffset = 0, endOffset = 0;
343 if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
344 startOffset = 0;
345 textAcc->GetCharacterCount(&endOffset);
346 rv = textAcc->GetText(startOffset, endOffset, text);
347 } else {
348 nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
349 if (boundaryType == -1)
350 return S_FALSE;
351 rv = textAcc->GetTextAfterOffset(aOffset, boundaryType,
352 &startOffset, &endOffset, text);
355 if (NS_FAILED(rv))
356 return GetHRESULT(rv);
358 *aStartOffset = startOffset;
359 *aEndOffset = endOffset;
361 if (text.IsEmpty())
362 return S_FALSE;
364 *aText = ::SysAllocStringLen(text.get(), text.Length());
365 return *aText ? S_OK : E_OUTOFMEMORY;
367 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
368 return E_FAIL;
371 STDMETHODIMP
372 CAccessibleText::get_textAtOffset(long aOffset,
373 enum IA2TextBoundaryType aBoundaryType,
374 long *aStartOffset, long *aEndOffset,
375 BSTR *aText)
377 __try {
378 *aStartOffset = 0;
379 *aEndOffset = 0;
380 *aText = NULL;
382 GET_NSIACCESSIBLETEXT
384 nsresult rv = NS_OK;
385 nsAutoString text;
386 PRInt32 startOffset = 0, endOffset = 0;
388 if (aBoundaryType == IA2_TEXT_BOUNDARY_ALL) {
389 startOffset = 0;
390 textAcc->GetCharacterCount(&endOffset);
391 rv = textAcc->GetText(startOffset, endOffset, text);
392 } else {
393 nsAccessibleTextBoundary boundaryType = GetGeckoTextBoundary(aBoundaryType);
394 if (boundaryType == -1)
395 return S_FALSE;
396 rv = textAcc->GetTextAtOffset(aOffset, boundaryType,
397 &startOffset, &endOffset, text);
400 if (NS_FAILED(rv))
401 return GetHRESULT(rv);
403 *aStartOffset = startOffset;
404 *aEndOffset = endOffset;
406 if (text.IsEmpty())
407 return S_FALSE;
409 *aText = ::SysAllocStringLen(text.get(), text.Length());
410 return *aText ? S_OK : E_OUTOFMEMORY;
412 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
413 return E_FAIL;
416 STDMETHODIMP
417 CAccessibleText::removeSelection(long aSelectionIndex)
419 __try {
420 GET_NSIACCESSIBLETEXT
422 nsresult rv = textAcc->RemoveSelection(aSelectionIndex);
423 return GetHRESULT(rv);
425 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
426 return E_FAIL;
429 STDMETHODIMP
430 CAccessibleText::setCaretOffset(long aOffset)
432 __try {
433 GET_NSIACCESSIBLETEXT
435 nsresult rv = textAcc->SetCaretOffset(aOffset);
436 return GetHRESULT(rv);
438 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
439 return E_FAIL;
442 STDMETHODIMP
443 CAccessibleText::setSelection(long aSelectionIndex, long aStartOffset,
444 long aEndOffset)
446 __try {
447 GET_NSIACCESSIBLETEXT
449 nsresult rv = textAcc->SetSelectionBounds(aSelectionIndex,
450 aStartOffset, aEndOffset);
451 return GetHRESULT(rv);
453 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
454 return E_FAIL;
457 STDMETHODIMP
458 CAccessibleText::get_nCharacters(long *aNCharacters)
460 __try {
461 *aNCharacters = 0;
463 GET_NSIACCESSIBLETEXT
465 PRInt32 charCount = 0;
466 nsresult rv = textAcc->GetCharacterCount(&charCount);
467 if (NS_FAILED(rv))
468 return GetHRESULT(rv);
470 *aNCharacters = charCount;
471 return S_OK;
473 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
474 return E_FAIL;
477 STDMETHODIMP
478 CAccessibleText::scrollSubstringTo(long aStartIndex, long aEndIndex,
479 enum IA2ScrollType aScrollType)
481 __try {
482 GET_NSIACCESSIBLETEXT
484 nsresult rv = textAcc->ScrollSubstringTo(aStartIndex, aEndIndex, aScrollType);
485 return GetHRESULT(rv);
487 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
488 return E_FAIL;
491 STDMETHODIMP
492 CAccessibleText::scrollSubstringToPoint(long aStartIndex, long aEndIndex,
493 enum IA2CoordinateType aCoordType,
494 long aX, long aY)
496 __try {
497 GET_NSIACCESSIBLETEXT
499 PRUint32 geckoCoordType = (aCoordType == IA2_COORDTYPE_SCREEN_RELATIVE) ?
500 nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
501 nsIAccessibleCoordinateType::COORDTYPE_PARENT_RELATIVE;
503 nsresult rv = textAcc->ScrollSubstringToPoint(aStartIndex, aEndIndex,
504 geckoCoordType, aX, aY);
505 return GetHRESULT(rv);
507 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
508 return E_FAIL;
511 STDMETHODIMP
512 CAccessibleText::get_newText(IA2TextSegment *aNewText)
514 __try {
515 return GetModifiedText(PR_TRUE, aNewText);
517 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
518 return E_FAIL;
521 STDMETHODIMP
522 CAccessibleText::get_oldText(IA2TextSegment *aOldText)
524 __try {
525 return GetModifiedText(PR_FALSE, aOldText);
527 } __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
528 return E_FAIL;
531 // CAccessibleText
533 HRESULT
534 CAccessibleText::GetModifiedText(PRBool aGetInsertedText,
535 IA2TextSegment *aText)
537 PRUint32 startOffset = 0, endOffset = 0;
538 nsAutoString text;
540 nsresult rv = GetModifiedText(aGetInsertedText, text,
541 &startOffset, &endOffset);
542 if (NS_FAILED(rv))
543 return GetHRESULT(rv);
545 aText->start = startOffset;
546 aText->end = endOffset;
548 if (text.IsEmpty())
549 return S_FALSE;
551 aText->text = ::SysAllocStringLen(text.get(), text.Length());
552 return aText->text ? S_OK : E_OUTOFMEMORY;
555 nsAccessibleTextBoundary
556 CAccessibleText::GetGeckoTextBoundary(enum IA2TextBoundaryType aBoundaryType)
558 switch (aBoundaryType) {
559 case IA2_TEXT_BOUNDARY_CHAR:
560 return nsIAccessibleText::BOUNDARY_CHAR;
561 case IA2_TEXT_BOUNDARY_WORD:
562 return nsIAccessibleText::BOUNDARY_WORD_START;
563 case IA2_TEXT_BOUNDARY_LINE:
564 return nsIAccessibleText::BOUNDARY_LINE_START;
565 //case IA2_TEXT_BOUNDARY_SENTENCE:
566 //case IA2_TEXT_BOUNDARY_PARAGRAPH:
567 // XXX: not implemented
568 default:
569 return -1;