Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #ifndef nsFrameSelection_h___
6 : #define nsFrameSelection_h___
7 :
8 : #include "mozilla/Attributes.h"
9 : #include "mozilla/EventForwards.h"
10 : #include "mozilla/dom/Selection.h"
11 : #include "mozilla/TextRange.h"
12 : #include "mozilla/UniquePtr.h"
13 : #include "nsIFrame.h"
14 : #include "nsIContent.h"
15 : #include "nsISelectionController.h"
16 : #include "nsISelectionListener.h"
17 : #include "nsITableCellLayout.h"
18 : #include "nsIDOMElement.h"
19 : #include "WordMovementType.h"
20 : #include "CaretAssociationHint.h"
21 : #include "nsBidiPresUtils.h"
22 :
23 : class nsRange;
24 :
25 : #define BIDI_LEVEL_UNDEFINED 0x80
26 :
27 : //----------------------------------------------------------------------
28 :
29 : // Selection interface
30 :
31 : struct SelectionDetails
32 : {
33 : #ifdef NS_BUILD_REFCNT_LOGGING
34 2 : SelectionDetails() {
35 2 : MOZ_COUNT_CTOR(SelectionDetails);
36 2 : }
37 4 : ~SelectionDetails() {
38 2 : MOZ_COUNT_DTOR(SelectionDetails);
39 2 : }
40 : #endif
41 : int32_t mStart;
42 : int32_t mEnd;
43 : mozilla::SelectionType mSelectionType;
44 : mozilla::TextRangeStyle mTextRangeStyle;
45 : mozilla::UniquePtr<SelectionDetails> mNext;
46 : };
47 :
48 : struct SelectionCustomColors
49 : {
50 : #ifdef NS_BUILD_REFCNT_LOGGING
51 0 : SelectionCustomColors()
52 0 : {
53 0 : MOZ_COUNT_CTOR(SelectionCustomColors);
54 0 : }
55 0 : ~SelectionCustomColors()
56 0 : {
57 0 : MOZ_COUNT_DTOR(SelectionCustomColors);
58 0 : }
59 : #endif
60 : mozilla::Maybe<nscolor> mForegroundColor;
61 : mozilla::Maybe<nscolor> mBackgroundColor;
62 : mozilla::Maybe<nscolor> mAltForegroundColor;
63 : mozilla::Maybe<nscolor> mAltBackgroundColor;
64 : };
65 :
66 : class nsIPresShell;
67 :
68 : /** PeekOffsetStruct is used to group various arguments (both input and output)
69 : * that are passed to nsFrame::PeekOffset(). See below for the description of
70 : * individual arguments.
71 : */
72 0 : struct MOZ_STACK_CLASS nsPeekOffsetStruct
73 : {
74 : nsPeekOffsetStruct(nsSelectionAmount aAmount,
75 : nsDirection aDirection,
76 : int32_t aStartOffset,
77 : nsPoint aDesiredPos,
78 : bool aJumpLines,
79 : bool aScrollViewStop,
80 : bool aIsKeyboardSelect,
81 : bool aVisual,
82 : bool aExtend,
83 : mozilla::EWordMovementType aWordMovementType = mozilla::eDefaultBehavior);
84 :
85 : // Note: Most arguments (input and output) are only used with certain values
86 : // of mAmount. These values are indicated for each argument below.
87 : // Arguments with no such indication are used with all values of mAmount.
88 :
89 : /*** Input arguments ***/
90 : // Note: The value of some of the input arguments may be changed upon exit.
91 :
92 : // mAmount: The type of movement requested (by character, word, line, etc.)
93 : nsSelectionAmount mAmount;
94 :
95 : // mDirection: eDirPrevious or eDirNext.
96 : // * Note for visual bidi movement:
97 : // eDirPrevious means 'left-then-up' if the containing block is LTR,
98 : // 'right-then-up' if it is RTL.
99 : // eDirNext means 'right-then-down' if the containing block is LTR,
100 : // 'left-then-down' if it is RTL.
101 : // Between paragraphs, eDirPrevious means "go to the visual end of the
102 : // previous paragraph", and eDirNext means "go to the visual beginning
103 : // of the next paragraph".
104 : // Used with: eSelectCharacter, eSelectWord, eSelectLine, eSelectParagraph.
105 : nsDirection mDirection;
106 :
107 : // mStartOffset: Offset into the content of the current frame where the peek starts.
108 : // Used with: eSelectCharacter, eSelectWord
109 : int32_t mStartOffset;
110 :
111 : // mDesiredPos: The desired inline coordinate for the caret
112 : // (one of .x or .y will be used, depending on line's writing mode)
113 : // Used with: eSelectLine.
114 : nsPoint mDesiredPos;
115 :
116 : // mWordMovementType: An enum that determines whether to prefer the start or end of a word
117 : // or to use the default beahvior, which is a combination of
118 : // direction and the platform-based pref
119 : // "layout.word_select.eat_space_to_next_word"
120 : mozilla::EWordMovementType mWordMovementType;
121 :
122 : // mJumpLines: Whether to allow jumping across line boundaries.
123 : // Used with: eSelectCharacter, eSelectWord.
124 : bool mJumpLines;
125 :
126 : // mScrollViewStop: Whether to stop when reaching a scroll view boundary.
127 : // Used with: eSelectCharacter, eSelectWord, eSelectLine.
128 : bool mScrollViewStop;
129 :
130 : // mIsKeyboardSelect: Whether the peeking is done in response to a keyboard action.
131 : // Used with: eSelectWord.
132 : bool mIsKeyboardSelect;
133 :
134 : // mVisual: Whether bidi caret behavior is visual (true) or logical (false).
135 : // Used with: eSelectCharacter, eSelectWord, eSelectBeginLine, eSelectEndLine.
136 : bool mVisual;
137 :
138 : // mExtend: Whether the selection is being extended or moved.
139 : bool mExtend;
140 :
141 : /*** Output arguments ***/
142 :
143 : // mResultContent: Content reached as a result of the peek.
144 : nsCOMPtr<nsIContent> mResultContent;
145 :
146 : // mResultFrame: Frame reached as a result of the peek.
147 : // Used with: eSelectCharacter, eSelectWord.
148 : nsIFrame *mResultFrame;
149 :
150 : // mContentOffset: Offset into content reached as a result of the peek.
151 : int32_t mContentOffset;
152 :
153 : // mAttachForward: When the result position is between two frames,
154 : // indicates which of the two frames the caret should be painted in.
155 : // false means "the end of the frame logically before the caret",
156 : // true means "the beginning of the frame logically after the caret".
157 : // Used with: eSelectLine, eSelectBeginLine, eSelectEndLine.
158 : mozilla::CaretAssociationHint mAttach;
159 : };
160 :
161 : struct nsPrevNextBidiLevels
162 : {
163 0 : void SetData(nsIFrame* aFrameBefore,
164 : nsIFrame* aFrameAfter,
165 : nsBidiLevel aLevelBefore,
166 : nsBidiLevel aLevelAfter)
167 : {
168 0 : mFrameBefore = aFrameBefore;
169 0 : mFrameAfter = aFrameAfter;
170 0 : mLevelBefore = aLevelBefore;
171 0 : mLevelAfter = aLevelAfter;
172 0 : }
173 : nsIFrame* mFrameBefore;
174 : nsIFrame* mFrameAfter;
175 : nsBidiLevel mLevelBefore;
176 : nsBidiLevel mLevelAfter;
177 : };
178 :
179 : namespace mozilla {
180 : namespace dom {
181 : class Selection;
182 : class SelectionChangeListener;
183 : } // namespace dom
184 : } // namespace mozilla
185 : class nsIScrollableFrame;
186 :
187 : /**
188 : * Methods which are marked with *unsafe* should be handled with special care.
189 : * They may cause nsFrameSelection to be deleted, if strong pointer isn't used,
190 : * or they may cause other objects to be deleted.
191 : */
192 : class nsFrameSelection final
193 : {
194 : public:
195 : typedef mozilla::CaretAssociationHint CaretAssociateHint;
196 :
197 : /*interfaces for addref and release and queryinterface*/
198 :
199 828 : NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsFrameSelection)
200 828 : NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsFrameSelection)
201 :
202 : /** Init will initialize the frame selector with the necessary pres shell to
203 : * be used by most of the methods
204 : * @param aShell is the parameter to be used for most of the other calls for callbacks etc
205 : * @param aLimiter limits the selection to nodes with aLimiter parents
206 : */
207 : void Init(nsIPresShell *aShell, nsIContent *aLimiter);
208 :
209 : /** HandleClick will take the focus to the new frame at the new offset and
210 : * will either extend the selection from the old anchor, or replace the old anchor.
211 : * the old anchor and focus position may also be used to deselect things
212 : * @param aNewfocus is the content that wants the focus
213 : * @param aContentOffset is the content offset of the parent aNewFocus
214 : * @param aContentOffsetEnd is the content offset of the parent aNewFocus and is specified different
215 : * when you need to select to and include both start and end points
216 : * @param aContinueSelection is the flag that tells the selection to keep the old anchor point or not.
217 : * @param aMultipleSelection will tell the frame selector to replace /or not the old selection.
218 : * cannot coexist with aContinueSelection
219 : * @param aHint will tell the selection which direction geometrically to actually show the caret on.
220 : * 1 = end of this line 0 = beginning of this line
221 : */
222 : /*unsafe*/
223 : nsresult HandleClick(nsIContent *aNewFocus,
224 : uint32_t aContentOffset,
225 : uint32_t aContentEndOffset,
226 : bool aContinueSelection,
227 : bool aMultipleSelection,
228 : CaretAssociateHint aHint);
229 :
230 : /** HandleDrag extends the selection to contain the frame closest to aPoint.
231 : * @param aPresContext is the context to use when figuring out what frame contains the point.
232 : * @param aFrame is the parent of all frames to use when searching for the closest frame to the point.
233 : * @param aPoint is relative to aFrame
234 : */
235 : /*unsafe*/
236 : void HandleDrag(nsIFrame *aFrame, nsPoint aPoint);
237 :
238 : /** HandleTableSelection will set selection to a table, cell, etc
239 : * depending on information contained in aFlags
240 : * @param aParentContent is the paretent of either a table or cell that user clicked or dragged the mouse in
241 : * @param aContentOffset is the offset of the table or cell
242 : * @param aTarget indicates what to select (defined in nsISelectionPrivate.idl/nsISelectionPrivate.h):
243 : * TABLESELECTION_CELL We should select a cell (content points to the cell)
244 : * TABLESELECTION_ROW We should select a row (content points to any cell in row)
245 : * TABLESELECTION_COLUMN We should select a row (content points to any cell in column)
246 : * TABLESELECTION_TABLE We should select a table (content points to the table)
247 : * TABLESELECTION_ALLCELLS We should select all cells (content points to any cell in table)
248 : * @param aMouseEvent passed in so we can get where event occurred and what keys are pressed
249 : */
250 : /*unsafe*/
251 : nsresult HandleTableSelection(nsINode* aParentContent,
252 : int32_t aContentOffset,
253 : int32_t aTarget,
254 : mozilla::WidgetMouseEvent* aMouseEvent);
255 :
256 : /**
257 : * Add cell to the selection.
258 : *
259 : * @param aCell [in] HTML td element.
260 : */
261 : nsresult SelectCellElement(nsIContent *aCell);
262 :
263 : /**
264 : * Add cells to the selection inside of the given cells range.
265 : *
266 : * @param aTable [in] HTML table element
267 : * @param aStartRowIndex [in] row index where the cells range starts
268 : * @param aStartColumnIndex [in] column index where the cells range starts
269 : * @param aEndRowIndex [in] row index where the cells range ends
270 : * @param aEndColumnIndex [in] column index where the cells range ends
271 : */
272 : nsresult AddCellsToSelection(nsIContent* aTable,
273 : int32_t aStartRowIndex,
274 : int32_t aStartColumnIndex,
275 : int32_t aEndRowIndex,
276 : int32_t aEndColumnIndex);
277 :
278 : /**
279 : * Remove cells from selection inside of the given cell range.
280 : *
281 : * @param aTable [in] HTML table element
282 : * @param aStartRowIndex [in] row index where the cells range starts
283 : * @param aStartColumnIndex [in] column index where the cells range starts
284 : * @param aEndRowIndex [in] row index where the cells range ends
285 : * @param aEndColumnIndex [in] column index where the cells range ends
286 : */
287 : nsresult RemoveCellsFromSelection(nsIContent* aTable,
288 : int32_t aStartRowIndex,
289 : int32_t aStartColumnIndex,
290 : int32_t aEndRowIndex,
291 : int32_t aEndColumnIndex);
292 :
293 : /**
294 : * Remove cells from selection outside of the given cell range.
295 : *
296 : * @param aTable [in] HTML table element
297 : * @param aStartRowIndex [in] row index where the cells range starts
298 : * @param aStartColumnIndex [in] column index where the cells range starts
299 : * @param aEndRowIndex [in] row index where the cells range ends
300 : * @param aEndColumnIndex [in] column index where the cells range ends
301 : */
302 : nsresult RestrictCellsToSelection(nsIContent* aTable,
303 : int32_t aStartRowIndex,
304 : int32_t aStartColumnIndex,
305 : int32_t aEndRowIndex,
306 : int32_t aEndColumnIndex);
307 :
308 : /** StartAutoScrollTimer is responsible for scrolling frames so that
309 : * aPoint is always visible, and for selecting any frame that contains
310 : * aPoint. The timer will also reset itself to fire again if we have
311 : * not scrolled to the end of the document.
312 : * @param aFrame is the outermost frame to use when searching for
313 : * the closest frame for the point, i.e. the frame that is capturing
314 : * the mouse
315 : * @param aPoint is relative to aFrame.
316 : * @param aDelay is the timer's interval.
317 : */
318 : /*unsafe*/
319 : nsresult StartAutoScrollTimer(nsIFrame *aFrame,
320 : nsPoint aPoint,
321 : uint32_t aDelay);
322 :
323 : /** StopAutoScrollTimer stops any active auto scroll timer.
324 : */
325 : void StopAutoScrollTimer();
326 :
327 : /** Lookup Selection
328 : * returns in frame coordinates the selection beginning and ending with the type of selection given
329 : * @param aContent is the content asking
330 : * @param aContentOffset is the starting content boundary
331 : * @param aContentLength is the length of the content piece asking
332 : * @param aSlowCheck will check using slow method with no shortcuts
333 : */
334 : mozilla::UniquePtr<SelectionDetails> LookUpSelection(nsIContent *aContent,
335 : int32_t aContentOffset,
336 : int32_t aContentLength,
337 : bool aSlowCheck) const;
338 :
339 : /** SetDragState(bool);
340 : * sets the drag state to aState for resons of drag state.
341 : * @param aState is the new state of drag
342 : */
343 : /*unsafe*/
344 : void SetDragState(bool aState);
345 :
346 : /** GetDragState(bool *);
347 : * gets the drag state to aState for resons of drag state.
348 : * @param aState will hold the state of drag
349 : */
350 4 : bool GetDragState() const { return mDragState; }
351 :
352 : /**
353 : if we are in table cell selection mode. aka ctrl click in table cell
354 : */
355 31 : bool GetTableCellSelection() const { return mSelectingTableCellMode != 0; }
356 22 : void ClearTableCellSelection() { mSelectingTableCellMode = 0; }
357 :
358 : /** GetSelection
359 : * no query interface for selection. must use this method now.
360 : * @param aSelectionType The selection type what you want.
361 : */
362 : mozilla::dom::Selection*
363 : GetSelection(mozilla::SelectionType aSelectionType) const;
364 :
365 : /**
366 : * ScrollSelectionIntoView scrolls a region of the selection,
367 : * so that it is visible in the scrolled view.
368 : *
369 : * @param aSelectionType the selection to scroll into view.
370 : * @param aRegion the region inside the selection to scroll into view.
371 : * @param aFlags the scroll flags. Valid bits include:
372 : * SCROLL_SYNCHRONOUS: when set, scrolls the selection into view
373 : * before returning. If not set, posts a request which is processed
374 : * at some point after the method returns.
375 : * SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled
376 : * into view.
377 : *
378 : */
379 : /*unsafe*/
380 : nsresult ScrollSelectionIntoView(mozilla::SelectionType aSelectionType,
381 : SelectionRegion aRegion,
382 : int16_t aFlags) const;
383 :
384 : /** RepaintSelection repaints the selected frames that are inside the selection
385 : * specified by aSelectionType.
386 : * @param aSelectionType The selection type what you want to repaint.
387 : */
388 : nsresult RepaintSelection(mozilla::SelectionType aSelectionType);
389 :
390 : /** GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and
391 : * the offset into that frame.
392 : * @param aNode input parameter for the node to look at
393 : * @param aOffset offset into above node.
394 : * @param aReturnOffset will contain offset into frame.
395 : */
396 : nsIFrame* GetFrameForNodeOffset(nsIContent* aNode,
397 : int32_t aOffset,
398 : CaretAssociateHint aHint,
399 : int32_t* aReturnOffset) const;
400 :
401 : /**
402 : * Scrolling then moving caret placement code in common to text areas and
403 : * content areas should be located in the implementer
404 : * This method will accept the following parameters and perform the scroll
405 : * and caret movement. It remains for the caller to call the final
406 : * ScrollCaretIntoView if that called wants to be sure the caret is always
407 : * visible.
408 : *
409 : * @param aForward if true, scroll forward if not scroll backward
410 : * @param aExtend if true, extend selection to the new point
411 : * @param aScrollableFrame the frame to scroll
412 : */
413 : /*unsafe*/
414 : void CommonPageMove(bool aForward,
415 : bool aExtend,
416 : nsIScrollableFrame* aScrollableFrame);
417 :
418 8 : void SetHint(CaretAssociateHint aHintRight) { mHint = aHintRight; }
419 13 : CaretAssociateHint GetHint() const { return mHint; }
420 :
421 : /**
422 : * SetCaretBidiLevel sets the caret bidi level.
423 : * @param aLevel the caret bidi level
424 : */
425 : void SetCaretBidiLevel(nsBidiLevel aLevel);
426 :
427 : /**
428 : * GetCaretBidiLevel gets the caret bidi level.
429 : */
430 : nsBidiLevel GetCaretBidiLevel() const;
431 :
432 : /**
433 : * UndefineCaretBidiLevel sets the caret bidi level to "undefined".
434 : */
435 : void UndefineCaretBidiLevel();
436 :
437 : /** PhysicalMove will generally be called from the nsiselectioncontroller implementations.
438 : * the effect being the selection will move one unit 'aAmount' in the
439 : * given aDirection.
440 : * @param aDirection the direction to move the selection
441 : * @param aAmount amount of movement (char/line; word/page; eol/doc)
442 : * @param aExtend continue selection
443 : */
444 : /*unsafe*/
445 : nsresult PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend);
446 :
447 : /** CharacterMove will generally be called from the nsiselectioncontroller implementations.
448 : * the effect being the selection will move one character left or right.
449 : * @param aForward move forward in document.
450 : * @param aExtend continue selection
451 : */
452 : /*unsafe*/
453 : nsresult CharacterMove(bool aForward, bool aExtend);
454 :
455 : /** CharacterExtendForDelete extends the selection forward (logically) to
456 : * the next character cell, so that the selected cell can be deleted.
457 : */
458 : /*unsafe*/
459 : nsresult CharacterExtendForDelete();
460 :
461 : /** CharacterExtendForBackspace extends the selection backward (logically) to
462 : * the previous character cell, so that the selected cell can be deleted.
463 : */
464 : /*unsafe*/
465 : nsresult CharacterExtendForBackspace();
466 :
467 : /** WordMove will generally be called from the nsiselectioncontroller implementations.
468 : * the effect being the selection will move one word left or right.
469 : * @param aForward move forward in document.
470 : * @param aExtend continue selection
471 : */
472 : /*unsafe*/
473 : nsresult WordMove(bool aForward, bool aExtend);
474 :
475 : /** WordExtendForDelete extends the selection backward or forward (logically) to the
476 : * next word boundary, so that the selected word can be deleted.
477 : * @param aForward select forward in document.
478 : */
479 : /*unsafe*/
480 : nsresult WordExtendForDelete(bool aForward);
481 :
482 : /** LineMove will generally be called from the nsiselectioncontroller implementations.
483 : * the effect being the selection will move one line up or down.
484 : * @param aForward move forward in document.
485 : * @param aExtend continue selection
486 : */
487 : /*unsafe*/
488 : nsresult LineMove(bool aForward, bool aExtend);
489 :
490 : /** IntraLineMove will generally be called from the nsiselectioncontroller implementations.
491 : * the effect being the selection will move to beginning or end of line
492 : * @param aForward move forward in document.
493 : * @param aExtend continue selection
494 : */
495 : /*unsafe*/
496 : nsresult IntraLineMove(bool aForward, bool aExtend);
497 :
498 : /** Select All will generally be called from the nsiselectioncontroller implementations.
499 : * it will select the whole doc
500 : */
501 : /*unsafe*/
502 : nsresult SelectAll();
503 :
504 : /** Sets/Gets The display selection enum.
505 : */
506 39 : void SetDisplaySelection(int16_t aState) { mDisplaySelection = aState; }
507 85 : int16_t GetDisplaySelection() const { return mDisplaySelection; }
508 :
509 : /** This method can be used to store the data received during a MouseDown
510 : * event so that we can place the caret during the MouseUp event.
511 : * @aMouseEvent the event received by the selection MouseDown
512 : * handling method. A nullptr value can be use to tell this method
513 : * that any data is storing is no longer valid.
514 : */
515 : void SetDelayedCaretData(mozilla::WidgetMouseEvent* aMouseEvent);
516 :
517 : /** Get the delayed MouseDown event data necessary to place the
518 : * caret during MouseUp processing.
519 : * @return a pointer to the event received
520 : * by the selection during MouseDown processing. It can be nullptr
521 : * if the data is no longer valid.
522 : */
523 0 : bool HasDelayedCaretData() { return mDelayedMouseEventValid; }
524 0 : bool IsShiftDownInDelayedCaretData()
525 : {
526 0 : NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data");
527 0 : return mDelayedMouseEventIsShift;
528 : }
529 0 : uint32_t GetClickCountInDelayedCaretData()
530 : {
531 0 : NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data");
532 0 : return mDelayedMouseEventClickCount;
533 : }
534 :
535 0 : bool MouseDownRecorded()
536 : {
537 0 : return !GetDragState() &&
538 0 : HasDelayedCaretData() &&
539 0 : GetClickCountInDelayedCaretData() < 2;
540 : }
541 :
542 : /** Get the content node that limits the selection
543 : * When searching up a nodes for parents, as in a text edit field
544 : * in an browser page, we must stop at this node else we reach into the
545 : * parent page, which is very bad!
546 : */
547 11 : nsIContent* GetLimiter() const { return mLimiter; }
548 :
549 7 : nsIContent* GetAncestorLimiter() const { return mAncestorLimiter; }
550 : /*unsafe*/
551 : void SetAncestorLimiter(nsIContent *aLimiter);
552 :
553 : /** This will tell the frame selection that a double click has been pressed
554 : * so it can track abort future drags if inside the same selection
555 : * @aDoubleDown has the double click down happened
556 : */
557 0 : void SetMouseDoubleDown(bool aDoubleDown) { mMouseDoubleDownState = aDoubleDown; }
558 :
559 : /** This will return whether the double down flag was set.
560 : * @return whether the double down flag was set
561 : */
562 : bool GetMouseDoubleDown() const { return mMouseDoubleDownState; }
563 :
564 : /**
565 : * GetPrevNextBidiLevels will return the frames and associated Bidi levels of the characters
566 : * logically before and after a (collapsed) selection.
567 : * @param aNode is the node containing the selection
568 : * @param aContentOffset is the offset of the selection in the node
569 : * @param aJumpLines If true, look across line boundaries.
570 : * If false, behave as if there were base-level frames at line edges.
571 : *
572 : * @return A struct holding the before/after frame and the before/after level.
573 : *
574 : * At the beginning and end of each line there is assumed to be a frame with
575 : * Bidi level equal to the paragraph embedding level.
576 : * In these cases the before frame and after frame respectively will be
577 : * nullptr.
578 : */
579 : nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent* aNode,
580 : uint32_t aContentOffset,
581 : bool aJumpLines) const;
582 :
583 : /** GetFrameFromLevel will scan in a given direction
584 : * until it finds a frame with a Bidi level less than or equal to a given level.
585 : * It will return the last frame before this.
586 : * @param aPresContext is the context to use
587 : * @param aFrameIn is the frame to start from
588 : * @param aDirection is the direction to scan
589 : * @param aBidiLevel is the level to search for
590 : * @param aFrameOut will hold the frame returned
591 : */
592 : nsresult GetFrameFromLevel(nsIFrame *aFrameIn,
593 : nsDirection aDirection,
594 : nsBidiLevel aBidiLevel,
595 : nsIFrame **aFrameOut) const;
596 :
597 : /**
598 : * MaintainSelection will track the current selection as being "sticky".
599 : * Dragging or extending selection will never allow for a subset
600 : * (or the whole) of the maintained selection to become unselected.
601 : * Primary use: double click selecting then dragging on second click
602 : * @param aAmount the initial amount of text selected (word, line or paragraph).
603 : * For "line", use eSelectBeginLine.
604 : */
605 : nsresult MaintainSelection(nsSelectionAmount aAmount = eSelectNoAmount);
606 :
607 : nsresult ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame,
608 : nsPoint& aPoint,
609 : nsIFrame **aRetFrame,
610 : nsPoint& aRetPoint);
611 :
612 : nsFrameSelection();
613 :
614 : void StartBatchChanges();
615 : void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON);
616 :
617 : /*unsafe*/
618 : nsresult DeleteFromDocument();
619 :
620 111 : nsIPresShell *GetShell()const { return mShell; }
621 :
622 : void DisconnectFromPresShell();
623 : nsresult ClearNormalSelection();
624 :
625 : private:
626 : ~nsFrameSelection();
627 :
628 : nsresult TakeFocus(nsIContent *aNewFocus,
629 : uint32_t aContentOffset,
630 : uint32_t aContentEndOffset,
631 : CaretAssociateHint aHint,
632 : bool aContinueSelection,
633 : bool aMultipleSelection);
634 :
635 : void BidiLevelFromMove(nsIPresShell* aPresShell,
636 : nsIContent *aNode,
637 : uint32_t aContentOffset,
638 : nsSelectionAmount aAmount,
639 : CaretAssociateHint aHint);
640 : void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset);
641 : nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode,
642 : uint32_t aContentOffset,
643 : CaretAssociateHint aHint,
644 : bool aJumpLines) const;
645 :
646 : bool AdjustForMaintainedSelection(nsIContent *aContent, int32_t aOffset);
647 :
648 : // post and pop reasons for notifications. we may stack these later
649 5 : void PostReason(int16_t aReason) { mSelectionChangeReason = aReason; }
650 36 : int16_t PopReason()
651 : {
652 36 : int16_t retval = mSelectionChangeReason;
653 36 : mSelectionChangeReason = nsISelectionListener::NO_REASON;
654 36 : return retval;
655 : }
656 0 : bool IsUserSelectionReason() const
657 : {
658 0 : return (mSelectionChangeReason &
659 : (nsISelectionListener::DRAG_REASON |
660 : nsISelectionListener::MOUSEDOWN_REASON |
661 : nsISelectionListener::MOUSEUP_REASON |
662 : nsISelectionListener::KEYPRESS_REASON)) !=
663 0 : nsISelectionListener::NO_REASON;
664 : }
665 :
666 : friend class mozilla::dom::Selection;
667 : friend class mozilla::dom::SelectionChangeListener;
668 : friend struct mozilla::AutoPrepareFocusRange;
669 : #ifdef DEBUG
670 : void printSelection(); // for debugging
671 : #endif /* DEBUG */
672 :
673 : void ResizeBuffer(uint32_t aNewBufSize);
674 :
675 : /*HELPER METHODS*/
676 : // Whether MoveCaret should use logical or visual movement,
677 : // or follow the bidi.edit.caret_movement_style preference.
678 : enum CaretMovementStyle {
679 : eLogical,
680 : eVisual,
681 : eUsePrefStyle
682 : };
683 : nsresult MoveCaret(nsDirection aDirection, bool aContinueSelection,
684 : nsSelectionAmount aAmount,
685 : CaretMovementStyle aMovementStyle);
686 :
687 : nsresult FetchDesiredPos(nsPoint &aDesiredPos); //the position requested by the Key Handling for up down
688 : void InvalidateDesiredPos(); //do not listen to mDesiredPos you must get another.
689 : void SetDesiredPos(nsPoint aPos); //set the mDesiredPos
690 :
691 39 : uint32_t GetBatching() const {return mBatching; }
692 : bool GetNotifyFrames() const { return mNotifyFrames; }
693 4 : void SetDirty(bool aDirty=true){if (mBatching) mChangesDuringBatching = aDirty;}
694 :
695 : // nsFrameSelection may get deleted when calling this,
696 : // so remember to use nsCOMPtr when needed.
697 : nsresult NotifySelectionListeners(mozilla::SelectionType aSelectionType);
698 : // Update the selection cache on repaint when the
699 : // selection being repainted is not empty.
700 : nsresult UpdateSelectionCacheOnRepaintSelection(mozilla::dom::
701 : Selection* aSel);
702 :
703 : RefPtr<mozilla::dom::Selection>
704 : mDomSelections[mozilla::kPresentSelectionTypeCount];
705 :
706 : // Table selection support.
707 : nsITableCellLayout* GetCellLayout(nsIContent *aCellContent) const;
708 :
709 : nsresult SelectBlockOfCells(nsIContent *aStartNode, nsIContent *aEndNode);
710 : nsresult SelectRowOrColumn(nsIContent *aCellContent, uint32_t aTarget);
711 : nsresult UnselectCells(nsIContent *aTable,
712 : int32_t aStartRowIndex, int32_t aStartColumnIndex,
713 : int32_t aEndRowIndex, int32_t aEndColumnIndex,
714 : bool aRemoveOutsideOfCellRange);
715 :
716 : nsresult GetCellIndexes(nsIContent *aCell, int32_t &aRowIndex, int32_t &aColIndex);
717 :
718 : // Get our first range, if its first selected node is a cell. If this does
719 : // not return null, then the first node in the returned range is a cell
720 : // (according to GetFirstCellNodeInRange).
721 : nsRange* GetFirstCellRange();
722 : // Get our next range, if its first selected node is a cell. If this does
723 : // not return null, then the first node in the returned range is a cell
724 : // (according to GetFirstCellNodeInRange).
725 : nsRange* GetNextCellRange();
726 : nsIContent* GetFirstCellNodeInRange(nsRange *aRange) const;
727 : // Returns non-null table if in same table, null otherwise
728 : nsIContent* IsInSameTable(nsIContent *aContent1, nsIContent *aContent2) const;
729 : // Might return null
730 : nsIContent* GetParentTable(nsIContent *aCellNode) const;
731 : nsresult CreateAndAddRange(nsINode* aContainer, int32_t aOffset);
732 :
733 : nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
734 : nsCOMPtr<nsIContent> mStartSelectedCell;
735 : nsCOMPtr<nsIContent> mEndSelectedCell;
736 : nsCOMPtr<nsIContent> mAppendStartSelectedCell;
737 : nsCOMPtr<nsIContent> mUnselectCellOnMouseUp;
738 : int32_t mSelectingTableCellMode;
739 : int32_t mSelectedCellIndex;
740 :
741 : // maintain selection
742 : RefPtr<nsRange> mMaintainRange;
743 : nsSelectionAmount mMaintainedAmount;
744 :
745 : //batching
746 : int32_t mBatching;
747 :
748 : // Limit selection navigation to a child of this node.
749 : nsCOMPtr<nsIContent> mLimiter;
750 : // Limit selection navigation to a descendant of this node.
751 : nsCOMPtr<nsIContent> mAncestorLimiter;
752 :
753 : nsIPresShell *mShell;
754 :
755 : int16_t mSelectionChangeReason; // reason for notifications of selection changing
756 : int16_t mDisplaySelection; //for visual display purposes.
757 :
758 : CaretAssociateHint mHint; //hint to tell if the selection is at the end of this line or beginning of next
759 : nsBidiLevel mCaretBidiLevel;
760 : nsBidiLevel mKbdBidiLevel;
761 :
762 : nsPoint mDesiredPos;
763 : uint32_t mDelayedMouseEventClickCount;
764 : bool mDelayedMouseEventIsShift;
765 : bool mDelayedMouseEventValid;
766 :
767 : bool mChangesDuringBatching;
768 : bool mNotifyFrames;
769 : bool mDragSelectingCells;
770 : bool mDragState; //for drag purposes
771 : bool mMouseDoubleDownState; //has the doubleclick down happened
772 : bool mDesiredPosSet;
773 :
774 : int8_t mCaretMovementStyle;
775 :
776 : static bool sSelectionEventsEnabled;
777 : static bool sSelectionEventsOnTextControlsEnabled;
778 : };
779 :
780 : #endif /* nsFrameSelection_h___ */
|