1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developers of the Original Code are
18 : * Sun Microsystems and IBM Corporation
19 : * Portions created by the Initial Developer are Copyright (C) 2006
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Ginn Chen (ginn.chen@sun.com)
24 : * Aaron Leventhal (aleventh@us.ibm.com)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef _nsHyperTextAccessible_H_
41 : #define _nsHyperTextAccessible_H_
42 :
43 : #include "nsIAccessibleText.h"
44 : #include "nsIAccessibleHyperText.h"
45 : #include "nsIAccessibleEditableText.h"
46 :
47 : #include "AccCollector.h"
48 : #include "nsAccessibleWrap.h"
49 :
50 : #include "nsFrameSelection.h"
51 : #include "nsISelectionController.h"
52 :
53 : enum EGetTextType { eGetBefore=-1, eGetAt=0, eGetAfter=1 };
54 :
55 : // This character marks where in the text returned via nsIAccessibleText(),
56 : // that embedded object characters exist
57 : const PRUnichar kEmbeddedObjectChar = 0xfffc;
58 : const PRUnichar kImaginaryEmbeddedObjectChar = ' ';
59 : const PRUnichar kForcedNewLineChar = '\n';
60 :
61 : #define NS_HYPERTEXTACCESSIBLE_IMPL_CID \
62 : { /* 245f3bc9-224f-4839-a92e-95239705f30b */ \
63 : 0x245f3bc9, \
64 : 0x224f, \
65 : 0x4839, \
66 : { 0xa9, 0x2e, 0x95, 0x23, 0x97, 0x05, 0xf3, 0x0b } \
67 : }
68 :
69 : /**
70 : * Special Accessible that knows how contain both text and embedded objects
71 : */
72 : class nsHyperTextAccessible : public nsAccessibleWrap,
73 : public nsIAccessibleText,
74 : public nsIAccessibleHyperText,
75 : public nsIAccessibleEditableText
76 : {
77 : public:
78 : nsHyperTextAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
79 0 : virtual ~nsHyperTextAccessible() { }
80 :
81 : NS_DECL_ISUPPORTS_INHERITED
82 : NS_DECL_NSIACCESSIBLETEXT
83 : NS_DECL_NSIACCESSIBLEHYPERTEXT
84 : NS_DECL_NSIACCESSIBLEEDITABLETEXT
85 : NS_DECLARE_STATIC_IID_ACCESSOR(NS_HYPERTEXTACCESSIBLE_IMPL_CID)
86 :
87 : // nsAccessible
88 : virtual PRInt32 GetLevelInternal();
89 : virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
90 : virtual nsresult GetNameInternal(nsAString& aName);
91 : virtual mozilla::a11y::role NativeRole();
92 : virtual PRUint64 NativeState();
93 :
94 : virtual void InvalidateChildren();
95 : virtual bool RemoveChild(nsAccessible* aAccessible);
96 :
97 : // nsHyperTextAccessible (static helper method)
98 :
99 : // Convert content offset to rendered text offset
100 : static nsresult ContentToRenderedOffset(nsIFrame *aFrame, PRInt32 aContentOffset,
101 : PRUint32 *aRenderedOffset);
102 :
103 : // Convert rendered text offset to content offset
104 : static nsresult RenderedToContentOffset(nsIFrame *aFrame, PRUint32 aRenderedOffset,
105 : PRInt32 *aContentOffset);
106 :
107 : //////////////////////////////////////////////////////////////////////////////
108 : // HyperLinkAccessible
109 :
110 : /**
111 : * Return link count within this hypertext accessible.
112 : */
113 0 : inline PRUint32 GetLinkCount()
114 : {
115 0 : return GetEmbeddedChildCount();
116 : }
117 :
118 : /**
119 : * Return link accessible at the given index.
120 : */
121 0 : inline nsAccessible* GetLinkAt(PRUint32 aIndex)
122 : {
123 0 : return GetEmbeddedChildAt(aIndex);
124 : }
125 :
126 : /**
127 : * Return index for the given link accessible.
128 : */
129 0 : inline PRInt32 GetLinkIndex(nsAccessible* aLink)
130 : {
131 0 : return GetIndexOfEmbeddedChild(aLink);
132 : }
133 :
134 : /**
135 : * Return link accessible at the given text offset.
136 : */
137 0 : inline PRInt32 GetLinkIndexAtOffset(PRUint32 aOffset)
138 : {
139 0 : nsAccessible* child = GetChildAtOffset(aOffset);
140 0 : return child ? GetLinkIndex(child) : -1;
141 : }
142 :
143 : //////////////////////////////////////////////////////////////////////////////
144 : // nsHyperTextAccessible: DOM point to text offset conversions.
145 :
146 : /**
147 : * Turn a DOM Node and offset into a character offset into this hypertext.
148 : * Will look for closest match when the DOM node does not have an accessible
149 : * object associated with it. Will return an offset for the end of
150 : * the string if the node is not found.
151 : *
152 : * @param aNode - the node to look for
153 : * @param aNodeOffset - the offset to look for
154 : * if -1 just look directly for the node
155 : * if >=0 and aNode is text, this represents a char offset
156 : * if >=0 and aNode is not text, this represents a child node offset
157 : * @param aResultOffset - the character offset into the current
158 : * nsHyperTextAccessible
159 : * @param aIsEndOffset - if true, then then this offset is not inclusive. The character
160 : * indicated by the offset returned is at [offset - 1]. This means
161 : * if the passed-in offset is really in a descendant, then the offset returned
162 : * will come just after the relevant embedded object characer.
163 : * If false, then the offset is inclusive. The character indicated
164 : * by the offset returned is at [offset]. If the passed-in offset in inside a
165 : * descendant, then the returned offset will be on the relevant embedded object char.
166 : *
167 : * @return the accessible child which contained the offset, if
168 : * it is within the current nsHyperTextAccessible,
169 : * otherwise nsnull
170 : */
171 : nsAccessible *DOMPointToHypertextOffset(nsINode *aNode,
172 : PRInt32 aNodeOffset,
173 : PRInt32 *aHypertextOffset,
174 : bool aIsEndOffset = false);
175 :
176 : /**
177 : * Turn a hypertext offsets into DOM point.
178 : *
179 : * @param aHTOffset [in] the given start hypertext offset
180 : * @param aNode [out] start node
181 : * @param aOffset [out] offset inside the start node
182 : */
183 : nsresult HypertextOffsetToDOMPoint(PRInt32 aHTOffset,
184 : nsIDOMNode **aNode,
185 : PRInt32 *aOffset);
186 :
187 : /**
188 : * Turn a start and end hypertext offsets into DOM range.
189 : *
190 : * @param aStartHTOffset [in] the given start hypertext offset
191 : * @param aEndHTOffset [in] the given end hypertext offset
192 : * @param aStartNode [out] start node of the range
193 : * @param aStartOffset [out] start offset of the range
194 : * @param aEndNode [out] end node of the range
195 : * @param aEndOffset [out] end offset of the range
196 : */
197 : nsresult HypertextOffsetsToDOMRange(PRInt32 aStartHTOffset,
198 : PRInt32 aEndHTOffset,
199 : nsIDOMNode **aStartNode,
200 : PRInt32 *aStartOffset,
201 : nsIDOMNode **aEndNode,
202 : PRInt32 *aEndOffset);
203 :
204 : //////////////////////////////////////////////////////////////////////////////
205 : // TextAccessible
206 :
207 : /**
208 : * Return character count within the hypertext accessible.
209 : */
210 0 : inline PRUint32 CharacterCount()
211 : {
212 0 : return GetChildOffset(GetChildCount());
213 : }
214 :
215 : /**
216 : * Get a character before/at/after the given offset.
217 : *
218 : * @param aOffset [in] the given offset
219 : * @param aShift [in] specifies whether to get a char before/at/after
220 : * offset
221 : * @param aChar [out] the character
222 : * @param aStartOffset [out, optional] the start offset of the character
223 : * @param aEndOffset [out, optional] the end offset of the character
224 : * @return false if offset at the given shift is out of range
225 : */
226 : bool GetCharAt(PRInt32 aOffset, EGetTextType aShift, nsAString& aChar,
227 : PRInt32* aStartOffset = nsnull, PRInt32* aEndOffset = nsnull);
228 :
229 : /**
230 : * Return text offset of the given child accessible within hypertext
231 : * accessible.
232 : *
233 : * @param aChild [in] accessible child to get text offset for
234 : * @param aInvalidateAfter [in, optional] indicates whether invalidate
235 : * cached offsets for next siblings of the child
236 : */
237 0 : PRInt32 GetChildOffset(nsAccessible* aChild,
238 : bool aInvalidateAfter = false)
239 : {
240 0 : PRInt32 index = GetIndexOf(aChild);
241 0 : return index == -1 ? -1 : GetChildOffset(index, aInvalidateAfter);
242 : }
243 :
244 : /**
245 : * Return text offset for the child accessible index.
246 : */
247 : PRInt32 GetChildOffset(PRUint32 aChildIndex,
248 : bool aInvalidateAfter = false);
249 :
250 : /**
251 : * Return child accessible at the given text offset.
252 : *
253 : * @param aOffset [in] the given text offset
254 : */
255 : PRInt32 GetChildIndexAtOffset(PRUint32 aOffset);
256 :
257 : /**
258 : * Return child accessible at the given text offset.
259 : *
260 : * @param aOffset [in] the given text offset
261 : */
262 0 : nsAccessible* GetChildAtOffset(PRUint32 aOffset)
263 : {
264 0 : return GetChildAt(GetChildIndexAtOffset(aOffset));
265 : }
266 :
267 : //////////////////////////////////////////////////////////////////////////////
268 : // EditableTextAccessible
269 :
270 : /**
271 : * Return the editor associated with the accessible.
272 : */
273 : virtual already_AddRefed<nsIEditor> GetEditor() const;
274 :
275 : protected:
276 : // nsHyperTextAccessible
277 :
278 : /**
279 : * Transform magic offset into text offset.
280 : */
281 0 : inline PRInt32 ConvertMagicOffset(PRInt32 aOffset)
282 : {
283 0 : if (aOffset == nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT)
284 0 : return CharacterCount();
285 :
286 0 : if (aOffset == nsIAccessibleText::TEXT_OFFSET_CARET) {
287 0 : PRInt32 caretOffset = -1;
288 0 : GetCaretOffset(&caretOffset);
289 0 : return caretOffset;
290 : }
291 :
292 0 : return aOffset;
293 : }
294 :
295 : /*
296 : * This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
297 : * @param aType, eGetBefore, eGetAt, eGetAfter
298 : * @param aBoundaryType, char/word-start/word-end/line-start/line-end/paragraph/attribute
299 : * @param aOffset, offset into the hypertext to start from
300 : * @param *aStartOffset, the resulting start offset for the returned substring
301 : * @param *aEndOffset, the resulting end offset for the returned substring
302 : * @param aText, the resulting substring
303 : * @return success/failure code
304 : */
305 : nsresult GetTextHelper(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
306 : PRInt32 aOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset,
307 : nsAString & aText);
308 :
309 : /**
310 : * Used by GetTextHelper() to move backward/forward from a given point
311 : * by word/line/etc.
312 : *
313 : * @param aPresShell the current presshell we're moving in
314 : * @param aFromFrame the starting frame we're moving from
315 : * @param aFromOffset the starting offset we're moving from
316 : * @param aFromAccessible the starting accessible we're moving from
317 : * @param aAmount how much are we moving (word/line/etc.) ?
318 : * @param aDirection forward or backward?
319 : * @param aNeedsStart for word and line cases, are we basing this on
320 : * the start or end?
321 : * @return the resulting offset into this hypertext
322 : */
323 : PRInt32 GetRelativeOffset(nsIPresShell *aPresShell, nsIFrame *aFromFrame,
324 : PRInt32 aFromOffset, nsAccessible *aFromAccessible,
325 : nsSelectionAmount aAmount, nsDirection aDirection,
326 : bool aNeedsStart);
327 :
328 : /**
329 : * Provides information for substring that is defined by the given start
330 : * and end offsets for this hyper text.
331 : *
332 : * @param aStartOffset [inout] the start offset into the hyper text. This
333 : * is also an out parameter used to return the offset
334 : * into the start frame's rendered text content
335 : * (start frame is the @return)
336 : *
337 : * @param aEndOffset [inout] the end offset into the hyper text. This is
338 : * also an out parameter used to return
339 : * the offset into the end frame's rendered
340 : * text content.
341 : *
342 : * @param aText [out, optional] return the substring's text
343 : * @param aEndFrame [out, optional] return the end frame for this
344 : * substring
345 : * @param aBoundsRect [out, optional] return the bounds rectangle for this
346 : * substring
347 : * @param aStartAcc [out, optional] return the start accessible for this
348 : * substring
349 : * @param aEndAcc [out, optional] return the end accessible for this
350 : * substring
351 : * @return the start frame for this substring
352 : */
353 : nsIFrame* GetPosAndText(PRInt32& aStartOffset, PRInt32& aEndOffset,
354 : nsAString *aText = nsnull,
355 : nsIFrame **aEndFrame = nsnull,
356 : nsIntRect *aBoundsRect = nsnull,
357 : nsAccessible **aStartAcc = nsnull,
358 : nsAccessible **aEndAcc = nsnull);
359 :
360 : nsIntRect GetBoundsForString(nsIFrame *aFrame, PRUint32 aStartRenderedOffset, PRUint32 aEndRenderedOffset);
361 :
362 : // Selection helpers
363 :
364 : /**
365 : * Return frame selection object for the accessible.
366 : */
367 : virtual already_AddRefed<nsFrameSelection> FrameSelection();
368 :
369 : /**
370 : * Return selection ranges within the accessible subtree.
371 : */
372 : void GetSelectionDOMRanges(PRInt16 aType, nsTArray<nsRange*>* aRanges);
373 :
374 : nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
375 :
376 : /**
377 : * Provide the line number for the caret, relative to the
378 : * current DOM node.
379 : * @return 1-based index for the line number with the caret
380 : */
381 : PRInt32 GetCaretLineNumber();
382 :
383 : // Helpers
384 : nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
385 : nsIAccessible *aAccessible,
386 : nsIDOMNode **aNode, PRInt32 *aNodeOffset);
387 :
388 :
389 : /**
390 : * Return hyper text offset for the specified bound of the given DOM range.
391 : * If the bound is outside of the hyper text then offset value is either
392 : * 0 or number of characters of hyper text, it depends on type of requested
393 : * offset. The method is a wrapper for DOMPointToHypertextOffset.
394 : *
395 : * @param aRange [in] the given range
396 : * @param aIsStartBound [in] specifies whether the required range bound is
397 : * start bound
398 : * @param aIsStartOffset [in] the offset type, used when the range bound is
399 : * outside of hyper text
400 : * @param aHTOffset [out] the result offset
401 : */
402 : nsresult RangeBoundToHypertextOffset(nsRange *aRange,
403 : bool aIsStartBound,
404 : bool aIsStartOffset,
405 : PRInt32 *aHTOffset);
406 :
407 : /**
408 : * Set 'misspelled' text attribute and return range offsets where the
409 : * attibute is stretched. If the text is not misspelled at the given offset
410 : * then we expose only range offsets where text is not misspelled. The method
411 : * is used by GetTextAttributes() method.
412 : *
413 : * @param aIncludeDefAttrs [in] points whether text attributes having default
414 : * values of attributes should be included
415 : * @param aSourceNode [in] the node we start to traverse from
416 : * @param aStartOffset [in, out] the start offset
417 : * @param aEndOffset [in, out] the end offset
418 : * @param aAttributes [out, optional] result attributes
419 : */
420 : nsresult GetSpellTextAttribute(nsINode* aNode, PRInt32 aNodeOffset,
421 : PRInt32 *aStartOffset,
422 : PRInt32 *aEndOffset,
423 : nsIPersistentProperties *aAttributes);
424 :
425 : private:
426 : /**
427 : * End text offsets array.
428 : */
429 : nsTArray<PRUint32> mOffsets;
430 : };
431 :
432 : NS_DEFINE_STATIC_IID_ACCESSOR(nsHyperTextAccessible,
433 : NS_HYPERTEXTACCESSIBLE_IMPL_CID)
434 :
435 :
436 : ////////////////////////////////////////////////////////////////////////////////
437 : // nsAccessible downcasting method
438 :
439 : inline nsHyperTextAccessible*
440 0 : nsAccessible::AsHyperText()
441 : {
442 : return mFlags & eHyperTextAccessible ?
443 0 : static_cast<nsHyperTextAccessible*>(this) : nsnull;
444 : }
445 :
446 : #endif // _nsHyperTextAccessible_H_
447 :
|