1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/Selection.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,287 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef mozilla_Selection_h__ 1.11 +#define mozilla_Selection_h__ 1.12 + 1.13 +#include "nsIWeakReference.h" 1.14 + 1.15 +#include "nsISelection.h" 1.16 +#include "nsISelectionController.h" 1.17 +#include "nsISelectionPrivate.h" 1.18 +#include "nsRange.h" 1.19 +#include "nsThreadUtils.h" 1.20 +#include "mozilla/TextRange.h" 1.21 +#include "nsWrapperCache.h" 1.22 + 1.23 +struct CachedOffsetForFrame; 1.24 +class nsAutoScrollTimer; 1.25 +class nsIContentIterator; 1.26 +class nsIFrame; 1.27 +class nsFrameSelection; 1.28 +struct SelectionDetails; 1.29 + 1.30 +namespace mozilla { 1.31 +class ErrorResult; 1.32 +} 1.33 + 1.34 +struct RangeData 1.35 +{ 1.36 + RangeData(nsRange* aRange) 1.37 + : mRange(aRange) 1.38 + {} 1.39 + 1.40 + nsRefPtr<nsRange> mRange; 1.41 + mozilla::TextRangeStyle mTextRangeStyle; 1.42 +}; 1.43 + 1.44 +// Note, the ownership of mozilla::dom::Selection depends on which way the 1.45 +// object is created. When nsFrameSelection has created Selection, 1.46 +// addreffing/releasing the Selection object is aggregated to nsFrameSelection. 1.47 +// Otherwise normal addref/release is used. This ensures that nsFrameSelection 1.48 +// is never deleted before its Selections. 1.49 +namespace mozilla { 1.50 +namespace dom { 1.51 + 1.52 +class Selection : public nsISelectionPrivate, 1.53 + public nsWrapperCache, 1.54 + public nsSupportsWeakReference 1.55 +{ 1.56 +public: 1.57 + Selection(); 1.58 + Selection(nsFrameSelection *aList); 1.59 + virtual ~Selection(); 1.60 + 1.61 + NS_DECL_CYCLE_COLLECTING_ISUPPORTS 1.62 + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Selection, nsISelectionPrivate) 1.63 + NS_DECL_NSISELECTION 1.64 + NS_DECL_NSISELECTIONPRIVATE 1.65 + 1.66 + nsIDocument* GetParentObject() const; 1.67 + 1.68 + // utility methods for scrolling the selection into view 1.69 + nsPresContext* GetPresContext() const; 1.70 + nsIPresShell* GetPresShell() const; 1.71 + nsFrameSelection* GetFrameSelection() const { return mFrameSelection; } 1.72 + // Returns a rect containing the selection region, and frame that that 1.73 + // position is relative to. For SELECTION_ANCHOR_REGION or 1.74 + // SELECTION_FOCUS_REGION the rect is a zero-width rectangle. For 1.75 + // SELECTION_WHOLE_SELECTION the rect contains both the anchor and focus 1.76 + // region rects. 1.77 + nsIFrame* GetSelectionAnchorGeometry(SelectionRegion aRegion, nsRect *aRect); 1.78 + // Returns the position of the region (SELECTION_ANCHOR_REGION or 1.79 + // SELECTION_FOCUS_REGION only), and frame that that position is relative to. 1.80 + // The 'position' is a zero-width rectangle. 1.81 + nsIFrame* GetSelectionEndPointGeometry(SelectionRegion aRegion, nsRect *aRect); 1.82 + 1.83 + nsresult PostScrollSelectionIntoViewEvent( 1.84 + SelectionRegion aRegion, 1.85 + int32_t aFlags, 1.86 + nsIPresShell::ScrollAxis aVertical, 1.87 + nsIPresShell::ScrollAxis aHorizontal); 1.88 + enum { 1.89 + SCROLL_SYNCHRONOUS = 1<<1, 1.90 + SCROLL_FIRST_ANCESTOR_ONLY = 1<<2, 1.91 + SCROLL_DO_FLUSH = 1<<3, 1.92 + SCROLL_OVERFLOW_HIDDEN = 1<<5 1.93 + }; 1.94 + // aDoFlush only matters if aIsSynchronous is true. If not, we'll just flush 1.95 + // when the scroll event fires so we make sure to scroll to the right place. 1.96 + nsresult ScrollIntoView(SelectionRegion aRegion, 1.97 + nsIPresShell::ScrollAxis aVertical = 1.98 + nsIPresShell::ScrollAxis(), 1.99 + nsIPresShell::ScrollAxis aHorizontal = 1.100 + nsIPresShell::ScrollAxis(), 1.101 + int32_t aFlags = 0); 1.102 + nsresult SubtractRange(RangeData* aRange, nsRange* aSubtract, 1.103 + nsTArray<RangeData>* aOutput); 1.104 + nsresult AddItem(nsRange *aRange, int32_t* aOutIndex); 1.105 + nsresult RemoveItem(nsRange *aRange); 1.106 + nsresult RemoveCollapsedRanges(); 1.107 + nsresult Clear(nsPresContext* aPresContext); 1.108 + nsresult Collapse(nsINode* aParentNode, int32_t aOffset); 1.109 + nsresult Extend(nsINode* aParentNode, int32_t aOffset); 1.110 + nsRange* GetRangeAt(int32_t aIndex); 1.111 + int32_t GetRangeCount() { return mRanges.Length(); } 1.112 + 1.113 + // Get the anchor-to-focus range if we don't care which end is 1.114 + // anchor and which end is focus. 1.115 + const nsRange* GetAnchorFocusRange() const { 1.116 + return mAnchorFocusRange; 1.117 + } 1.118 + 1.119 + nsDirection GetDirection(){return mDirection;} 1.120 + void SetDirection(nsDirection aDir){mDirection = aDir;} 1.121 + nsresult SetAnchorFocusToRange(nsRange *aRange); 1.122 + void ReplaceAnchorFocusRange(nsRange *aRange); 1.123 + 1.124 + // NS_IMETHOD GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, int32_t aOffset, bool aIsEndNode, nsIFrame **aResultFrame); 1.125 + NS_IMETHOD GetPrimaryFrameForAnchorNode(nsIFrame **aResultFrame); 1.126 + NS_IMETHOD GetPrimaryFrameForFocusNode(nsIFrame **aResultFrame, int32_t *aOffset, bool aVisual); 1.127 + NS_IMETHOD LookUpSelection(nsIContent *aContent, int32_t aContentOffset, int32_t aContentLength, 1.128 + SelectionDetails **aReturnDetails, SelectionType aType, bool aSlowCheck); 1.129 + NS_IMETHOD Repaint(nsPresContext* aPresContext); 1.130 + 1.131 + // Note: StartAutoScrollTimer might destroy arbitrary frames etc. 1.132 + nsresult StartAutoScrollTimer(nsIFrame *aFrame, 1.133 + nsPoint& aPoint, 1.134 + uint32_t aDelay); 1.135 + 1.136 + nsresult StopAutoScrollTimer(); 1.137 + 1.138 + JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; 1.139 + 1.140 + // WebIDL methods 1.141 + nsINode* GetAnchorNode(); 1.142 + uint32_t AnchorOffset(); 1.143 + nsINode* GetFocusNode(); 1.144 + uint32_t FocusOffset(); 1.145 + 1.146 + bool IsCollapsed(); 1.147 + void Collapse(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv); 1.148 + void CollapseToStart(mozilla::ErrorResult& aRv); 1.149 + void CollapseToEnd(mozilla::ErrorResult& aRv); 1.150 + 1.151 + void Extend(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv); 1.152 + 1.153 + void SelectAllChildren(nsINode& aNode, mozilla::ErrorResult& aRv); 1.154 + void DeleteFromDocument(mozilla::ErrorResult& aRv); 1.155 + 1.156 + uint32_t RangeCount() const 1.157 + { 1.158 + return mRanges.Length(); 1.159 + } 1.160 + nsRange* GetRangeAt(uint32_t aIndex, mozilla::ErrorResult& aRv); 1.161 + void AddRange(nsRange& aRange, mozilla::ErrorResult& aRv); 1.162 + void RemoveRange(nsRange& aRange, mozilla::ErrorResult& aRv); 1.163 + void RemoveAllRanges(mozilla::ErrorResult& aRv); 1.164 + 1.165 + void Stringify(nsAString& aResult); 1.166 + 1.167 + bool ContainsNode(nsINode* aNode, bool aPartlyContained, mozilla::ErrorResult& aRv); 1.168 + 1.169 + void Modify(const nsAString& aAlter, const nsAString& aDirection, 1.170 + const nsAString& aGranularity, mozilla::ErrorResult& aRv); 1.171 + 1.172 + bool GetInterlinePosition(mozilla::ErrorResult& aRv); 1.173 + void SetInterlinePosition(bool aValue, mozilla::ErrorResult& aRv); 1.174 + 1.175 + void ToStringWithFormat(const nsAString& aFormatType, 1.176 + uint32_t aFlags, 1.177 + int32_t aWrapColumn, 1.178 + nsAString& aReturn, 1.179 + mozilla::ErrorResult& aRv); 1.180 + void AddSelectionListener(nsISelectionListener* aListener, 1.181 + mozilla::ErrorResult& aRv); 1.182 + void RemoveSelectionListener(nsISelectionListener* aListener, 1.183 + mozilla::ErrorResult& aRv); 1.184 + 1.185 + int16_t Type() const { return mType; } 1.186 + 1.187 + void GetRangesForInterval(nsINode& aBeginNode, int32_t aBeginOffset, 1.188 + nsINode& aEndNode, int32_t aEndOffset, 1.189 + bool aAllowAdjacent, 1.190 + nsTArray<nsRefPtr<nsRange>>& aReturn, 1.191 + mozilla::ErrorResult& aRv); 1.192 + 1.193 + void ScrollIntoView(int16_t aRegion, bool aIsSynchronous, 1.194 + int16_t aVPercent, int16_t aHPercent, 1.195 + mozilla::ErrorResult& aRv); 1.196 + 1.197 +private: 1.198 + friend class ::nsAutoScrollTimer; 1.199 + 1.200 + // Note: DoAutoScroll might destroy arbitrary frames etc. 1.201 + nsresult DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint); 1.202 + 1.203 +public: 1.204 + SelectionType GetType(){return mType;} 1.205 + void SetType(SelectionType aType){mType = aType;} 1.206 + 1.207 + nsresult NotifySelectionListeners(); 1.208 + 1.209 +private: 1.210 + 1.211 + class ScrollSelectionIntoViewEvent; 1.212 + friend class ScrollSelectionIntoViewEvent; 1.213 + 1.214 + class ScrollSelectionIntoViewEvent : public nsRunnable { 1.215 + public: 1.216 + NS_DECL_NSIRUNNABLE 1.217 + ScrollSelectionIntoViewEvent(Selection* aSelection, 1.218 + SelectionRegion aRegion, 1.219 + nsIPresShell::ScrollAxis aVertical, 1.220 + nsIPresShell::ScrollAxis aHorizontal, 1.221 + int32_t aFlags) 1.222 + : mSelection(aSelection), 1.223 + mRegion(aRegion), 1.224 + mVerticalScroll(aVertical), 1.225 + mHorizontalScroll(aHorizontal), 1.226 + mFlags(aFlags) { 1.227 + NS_ASSERTION(aSelection, "null parameter"); 1.228 + } 1.229 + void Revoke() { mSelection = nullptr; } 1.230 + private: 1.231 + Selection *mSelection; 1.232 + SelectionRegion mRegion; 1.233 + nsIPresShell::ScrollAxis mVerticalScroll; 1.234 + nsIPresShell::ScrollAxis mHorizontalScroll; 1.235 + int32_t mFlags; 1.236 + }; 1.237 + 1.238 + void setAnchorFocusRange(int32_t aIndex); // pass in index into mRanges; 1.239 + // negative value clears 1.240 + // mAnchorFocusRange 1.241 + nsresult SelectAllFramesForContent(nsIContentIterator *aInnerIter, 1.242 + nsIContent *aContent, 1.243 + bool aSelected); 1.244 + nsresult selectFrames(nsPresContext* aPresContext, nsRange *aRange, bool aSelect); 1.245 + nsresult getTableCellLocationFromRange(nsRange *aRange, int32_t *aSelectionType, int32_t *aRow, int32_t *aCol); 1.246 + nsresult addTableCellRange(nsRange *aRange, bool *aDidAddRange, int32_t *aOutIndex); 1.247 + 1.248 + nsresult FindInsertionPoint( 1.249 + nsTArray<RangeData>* aElementArray, 1.250 + nsINode* aPointNode, int32_t aPointOffset, 1.251 + nsresult (*aComparator)(nsINode*,int32_t,nsRange*,int32_t*), 1.252 + int32_t* aPoint); 1.253 + bool EqualsRangeAtPoint(nsINode* aBeginNode, int32_t aBeginOffset, 1.254 + nsINode* aEndNode, int32_t aEndOffset, 1.255 + int32_t aRangeIndex); 1.256 + nsresult GetIndicesForInterval(nsINode* aBeginNode, int32_t aBeginOffset, 1.257 + nsINode* aEndNode, int32_t aEndOffset, 1.258 + bool aAllowAdjacent, 1.259 + int32_t* aStartIndex, int32_t* aEndIndex); 1.260 + RangeData* FindRangeData(nsIDOMRange* aRange); 1.261 + 1.262 + // These are the ranges inside this selection. They are kept sorted in order 1.263 + // of DOM start position. 1.264 + // 1.265 + // This data structure is sorted by the range beginnings. As the ranges are 1.266 + // disjoint, it is also implicitly sorted by the range endings. This allows 1.267 + // us to perform binary searches when searching for existence of a range, 1.268 + // giving us O(log n) search time. 1.269 + // 1.270 + // Inserting a new range requires finding the overlapping interval, requiring 1.271 + // two binary searches plus up to an additional 6 DOM comparisons. If this 1.272 + // proves to be a performance concern, then an interval tree may be a 1.273 + // possible solution, allowing the calculation of the overlap interval in 1.274 + // O(log n) time, though this would require rebalancing and other overhead. 1.275 + nsTArray<RangeData> mRanges; 1.276 + 1.277 + nsRefPtr<nsRange> mAnchorFocusRange; 1.278 + nsRefPtr<nsFrameSelection> mFrameSelection; 1.279 + nsRefPtr<nsAutoScrollTimer> mAutoScrollTimer; 1.280 + nsCOMArray<nsISelectionListener> mSelectionListeners; 1.281 + nsRevocableEventPtr<ScrollSelectionIntoViewEvent> mScrollEvent; 1.282 + CachedOffsetForFrame *mCachedOffsetForFrame; 1.283 + nsDirection mDirection; 1.284 + SelectionType mType; 1.285 +}; 1.286 + 1.287 +} // namespace dom 1.288 +} // namespace mozilla 1.289 + 1.290 +#endif // mozilla_Selection_h__