1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_a11y_TextRange_h__ 8 #define mozilla_a11y_TextRange_h__ 9 10 #include "mozilla/Move.h" 11 #include "nsCaseTreatment.h" 12 #include "nsRect.h" 13 #include "nsTArray.h" 14 15 class nsIVariant; 16 17 namespace mozilla { 18 namespace a11y { 19 20 class Accessible; 21 class HyperTextAccessible; 22 23 /** 24 * A text point (hyper text + offset), represents a boundary of text range. 25 */ 26 struct TextPoint final 27 { TextPointfinal28 TextPoint(HyperTextAccessible* aContainer, int32_t aOffset) : 29 mContainer(aContainer), mOffset(aOffset) { } TextPointfinal30 TextPoint(const TextPoint& aPoint) : 31 mContainer(aPoint.mContainer), mOffset(aPoint.mOffset) { } 32 33 HyperTextAccessible* mContainer; 34 int32_t mOffset; 35 36 bool operator ==(const TextPoint& aPoint) const 37 { return mContainer == aPoint.mContainer && mOffset == aPoint.mOffset; } 38 bool operator <(const TextPoint& aPoint) const; 39 }; 40 41 /** 42 * Represents a text range within the text control or document. 43 */ 44 class TextRange final 45 { 46 public: 47 TextRange(HyperTextAccessible* aRoot, 48 HyperTextAccessible* aStartContainer, int32_t aStartOffset, 49 HyperTextAccessible* aEndContainer, int32_t aEndOffset); TextRange()50 TextRange() {} TextRange(TextRange && aRange)51 TextRange(TextRange&& aRange) : 52 mRoot(mozilla::Move(aRange.mRoot)), 53 mStartContainer(mozilla::Move(aRange.mStartContainer)), 54 mEndContainer(mozilla::Move(aRange.mEndContainer)), 55 mStartOffset(aRange.mStartOffset), mEndOffset(aRange.mEndOffset) {} 56 57 TextRange& operator= (TextRange&& aRange) 58 { 59 mRoot = mozilla::Move(aRange.mRoot); 60 mStartContainer = mozilla::Move(aRange.mStartContainer); 61 mEndContainer = mozilla::Move(aRange.mEndContainer); 62 mStartOffset = aRange.mStartOffset; 63 mEndOffset = aRange.mEndOffset; 64 return *this; 65 } 66 StartContainer()67 HyperTextAccessible* StartContainer() const { return mStartContainer; } StartOffset()68 int32_t StartOffset() const { return mStartOffset; } EndContainer()69 HyperTextAccessible* EndContainer() const { return mEndContainer; } EndOffset()70 int32_t EndOffset() const { return mEndOffset; } 71 72 bool operator ==(const TextRange& aRange) const 73 { 74 return mStartContainer == aRange.mStartContainer && 75 mStartOffset == aRange.mStartOffset && 76 mEndContainer == aRange.mEndContainer && mEndOffset == aRange.mEndOffset; 77 } 78 StartPoint()79 TextPoint StartPoint() const { return TextPoint(mStartContainer, mStartOffset); } EndPoint()80 TextPoint EndPoint() const { return TextPoint(mEndContainer, mEndOffset); } 81 82 /** 83 * Return a container containing both start and end points. 84 */ 85 Accessible* Container() const; 86 87 /** 88 * Return a list of embedded objects enclosed by the text range (includes 89 * partially overlapped objects). 90 */ 91 void EmbeddedChildren(nsTArray<Accessible*>* aChildren) const; 92 93 /** 94 * Return text enclosed by the range. 95 */ 96 void Text(nsAString& aText) const; 97 98 /** 99 * Return list of bounding rects of the text range by lines. 100 */ 101 void Bounds(nsTArray<nsIntRect> aRects) const; 102 103 enum ETextUnit { 104 eFormat, 105 eWord, 106 eLine, 107 eParagraph, 108 ePage, 109 eDocument 110 }; 111 112 /** 113 * Move the range or its points on specified amount of given units. 114 */ Move(ETextUnit aUnit,int32_t aCount)115 void Move(ETextUnit aUnit, int32_t aCount) 116 { 117 MoveEnd(aUnit, aCount); 118 MoveStart(aUnit, aCount); 119 } MoveStart(ETextUnit aUnit,int32_t aCount)120 void MoveStart(ETextUnit aUnit, int32_t aCount) 121 { 122 MoveInternal(aUnit, aCount, *mStartContainer, mStartOffset, 123 mEndContainer, mEndOffset); 124 } MoveEnd(ETextUnit aUnit,int32_t aCount)125 void MoveEnd(ETextUnit aUnit, int32_t aCount) 126 { MoveInternal(aUnit, aCount, *mEndContainer, mEndOffset); } 127 128 /** 129 * Move the range points to the closest unit boundaries. 130 */ 131 void Normalize(ETextUnit aUnit); 132 133 /** 134 * Crops the range if it overlaps the given accessible element boundaries, 135 * returns true if the range was cropped successfully. 136 */ 137 bool Crop(Accessible* aContainer); 138 139 enum EDirection { 140 eBackward, 141 eForward 142 }; 143 144 /** 145 * Return range enclosing the found text. 146 */ 147 void FindText(const nsAString& aText, EDirection aDirection, 148 nsCaseTreatment aCaseSensitive, TextRange* aFoundRange) const; 149 150 enum EAttr { 151 eAnimationStyleAttr, 152 eAnnotationObjectsAttr, 153 eAnnotationTypesAttr, 154 eBackgroundColorAttr, 155 eBulletStyleAttr, 156 eCapStyleAttr, 157 eCaretBidiModeAttr, 158 eCaretPositionAttr, 159 eCultureAttr, 160 eFontNameAttr, 161 eFontSizeAttr, 162 eFontWeightAttr, 163 eForegroundColorAttr, 164 eHorizontalTextAlignmentAttr, 165 eIndentationFirstLineAttr, 166 eIndentationLeadingAttr, 167 eIndentationTrailingAttr, 168 eIsActiveAttr, 169 eIsHiddenAttr, 170 eIsItalicAttr, 171 eIsReadOnlyAttr, 172 eIsSubscriptAttr, 173 eIsSuperscriptAttr, 174 eLinkAttr, 175 eMarginBottomAttr, 176 eMarginLeadingAttr, 177 eMarginTopAttr, 178 eMarginTrailingAttr, 179 eOutlineStylesAttr, 180 eOverlineColorAttr, 181 eOverlineStyleAttr, 182 eSelectionActiveEndAttr, 183 eStrikethroughColorAttr, 184 eStrikethroughStyleAttr, 185 eStyleIdAttr, 186 eStyleNameAttr, 187 eTabsAttr, 188 eTextFlowDirectionsAttr, 189 eUnderlineColorAttr, 190 eUnderlineStyleAttr 191 }; 192 193 /** 194 * Return range enclosing text having requested attribute. 195 */ 196 void FindAttr(EAttr aAttr, nsIVariant* aValue, EDirection aDirection, 197 TextRange* aFoundRange) const; 198 199 /** 200 * Add/remove the text range from selection. 201 */ 202 void AddToSelection() const; 203 void RemoveFromSelection() const; 204 void Select() const; 205 206 /** 207 * Scroll the text range into view. 208 */ 209 enum EHowToAlign { 210 eAlignToTop, 211 eAlignToBottom 212 }; 213 void ScrollIntoView(EHowToAlign aHow) const; 214 215 /** 216 * Return true if this TextRange object represents an actual range of text. 217 */ IsValid()218 bool IsValid() const { return mRoot; } 219 SetStartPoint(HyperTextAccessible * aContainer,int32_t aOffset)220 void SetStartPoint(HyperTextAccessible* aContainer, int32_t aOffset) 221 { mStartContainer = aContainer; mStartOffset = aOffset; } SetEndPoint(HyperTextAccessible * aContainer,int32_t aOffset)222 void SetEndPoint(HyperTextAccessible* aContainer, int32_t aOffset) 223 { mStartContainer = aContainer; mStartOffset = aOffset; } 224 225 private: 226 TextRange(const TextRange& aRange) = delete; 227 TextRange& operator=(const TextRange& aRange) = delete; 228 229 friend class HyperTextAccessible; 230 friend class xpcAccessibleTextRange; 231 232 void Set(HyperTextAccessible* aRoot, 233 HyperTextAccessible* aStartContainer, int32_t aStartOffset, 234 HyperTextAccessible* aEndContainer, int32_t aEndOffset); 235 236 /** 237 * Text() method helper. 238 * @param aText [in,out] calculated text 239 * @param aCurrent [in] currently traversed node 240 * @param aStartIntlOffset [in] start offset if current node is a text node 241 * @return true if calculation is not finished yet 242 */ 243 bool TextInternal(nsAString& aText, Accessible* aCurrent, 244 uint32_t aStartIntlOffset) const; 245 246 void MoveInternal(ETextUnit aUnit, int32_t aCount, 247 HyperTextAccessible& aContainer, int32_t aOffset, 248 HyperTextAccessible* aStopContainer = nullptr, 249 int32_t aStopOffset = 0); 250 251 /** 252 * A helper method returning a common parent for two given accessible 253 * elements. 254 */ 255 Accessible* CommonParent(Accessible* aAcc1, Accessible* aAcc2, 256 nsTArray<Accessible*>* aParents1, uint32_t* aPos1, 257 nsTArray<Accessible*>* aParents2, uint32_t* aPos2) const; 258 259 RefPtr<HyperTextAccessible> mRoot; 260 RefPtr<HyperTextAccessible> mStartContainer; 261 RefPtr<HyperTextAccessible> mEndContainer; 262 int32_t mStartOffset; 263 int32_t mEndOffset; 264 }; 265 266 267 } // namespace a11y 268 } // namespace mozilla 269 270 #endif 271