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