4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
9 * Full author contact details are available in file CREDITS.
15 #include "DispatchResult.h"
16 #include "DocIterator.h"
20 #include "mathed/MathParser_flags.h"
32 class InsetMathUnknown;
36 * This class describes the position of a cursor within a document,
37 * but does not contain any detail about the view. It is currently
38 * only used to save cursor position in Undo, but culd be extended to
39 * handle the methods that only need this data.
41 class CursorData : public DocIterator
47 explicit CursorData(Buffer * buffer);
49 explicit CursorData(DocIterator const & dit);
51 /// the anchor position
54 mutable DispatchResult disp_;
55 /// do we have a selection?
57 /// are we on the way to get one?
59 /// are we in word-selection mode? This is set when double clicking.
61 /// If true, we are behind the previous char, otherwise we are in front
62 // of the next char. This only make a difference when we are in front
63 // of a big inset spanning a whole row and computing coordinates for
64 // displaying the cursor.
67 // FIXME: make them protected.
69 /// the current font settings
72 Font real_current_font;
77 // math specific stuff that could be promoted to "global" later
79 /// do we allow autocorrection
81 /// are we entering a macro name?
86 /// The cursor class describes the position of a cursor within a document.
87 class Cursor : public CursorData
90 /// create the cursor of a BufferView
91 explicit Cursor(BufferView & bv);
93 /// returns true if we made a decision
94 bool getStatus(FuncRequest const & cmd, FuncStatus & flag) const;
95 /// dispatch from innermost inset upwards
96 void dispatch(FuncRequest const & cmd);
97 /// get the resut of the last dispatch
98 DispatchResult const & result() const;
99 /// add a new cursor slice
100 void push(Inset & inset);
101 /// add a new cursor slice, place cursor at front (move backwards)
102 void pushBackward(Inset & inset);
103 /// pop one level off the cursor
105 /// pop one slice off the cursor stack and go backwards
107 /// pop one slice off the cursor stack and go forward
109 /// make sure we are outside of given inset
110 void leaveInset(Inset const & inset);
111 /// set the cursor data
112 void setCursorData(CursorData const & data);
114 void setCursor(DocIterator const & it);
115 /// sets the cursor to the normalized selection anchor
116 void setCursorToAnchor();
119 void setCurrentFont();
124 /// selection active?
125 bool selection() const { return selection_; }
127 void setSelection(bool sel) { selection_ = sel; }
128 /// do we have a multicell selection?
129 bool selIsMultiCell() const
130 { return selection_ && selBegin().idx() != selEnd().idx(); }
131 /// do we have a multiline selection?
132 bool selIsMultiLine() const
133 { return selection_ && selBegin().pit() != selEnd().pit(); }
135 void setWordSelection(bool set) { word_selection_ = set; }
137 bool wordSelection() { return word_selection_; }
138 /// did we place the anchor?
139 bool mark() const { return mark_; }
140 /// did we place the anchor?
141 void setMark(bool mark) { mark_ = mark; }
144 /// set selection at given position
145 void setSelection(DocIterator const & where, int n);
147 void clearSelection();
148 /// access start of selection
149 CursorSlice selBegin() const;
150 /// access end of selection
151 CursorSlice selEnd() const;
152 /// access start of selection
153 DocIterator selectionBegin() const;
154 /// access end of selection
155 DocIterator selectionEnd() const;
157 * Update the selection status and save permanent
158 * selection if needed.
159 * @param selecting the new selection status
160 * @return whether the selection status has changed
162 bool selHandle(bool selecting);
164 docstring selectionAsString(bool with_label) const;
166 docstring currentState() const;
168 /// auto-correct mode
169 bool autocorrect() const { return autocorrect_; }
170 /// auto-correct mode
171 bool & autocorrect() { return autocorrect_; }
172 /// are we entering a macro name?
173 bool macromode() const { return macromode_; }
174 /// are we entering a macro name?
175 bool & macromode() { return macromode_; }
176 /// returns x,y position
177 void getPos(int & x, int & y) const;
178 /// return logical positions between which the cursor is situated
180 * If the cursor is at the edge of a row, the position which is "over the
181 * edge" will be returned as -1.
183 void getSurroundingPos(pos_type & left_pos, pos_type & right_pos);
184 /// the row in the paragraph we're in
185 Row const & textRow() const;
190 /// move one step backwards
192 /// move one step forward
194 /// move visually one step to the right
196 * @note: This method may move into an inset unless skip_inset == true.
197 * @note: This method may move into a new paragraph.
198 * @note: This method may move out of the current slice.
199 * @return: true if moved, false if not moved
201 bool posVisRight(bool skip_inset = false);
202 /// move visually one step to the left
204 * @note: This method may move into an inset unless skip_inset == true.
205 * @note: This method may move into a new paragraph.
206 * @note: This method may move out of the current slice.
207 * @return: true if moved, false if not moved
209 bool posVisLeft(bool skip_inset = false);
210 /// move visually to next/previous row
212 * Assuming we were to keep moving left (right) from the current cursor
213 * position, place the cursor at the rightmost (leftmost) edge of the
214 * new row to which we would move according to visual-mode cursor movement.
215 * This could be either the next or the previous row, depending on the
216 * direction in which we're moving, and whether we're in an LTR or RTL
218 * @note: The new position may even be in a new paragraph.
219 * @note: This method will not move out of the current slice.
220 * @return: false if not moved (no more rows to move to in given direction)
221 * @return: true if moved
223 bool posVisToNewRow(bool movingLeft);
224 /// move to right or left extremity of the current row
225 void posVisToRowExtremity(bool left);
228 void insert(Inset *);
229 /// insert a single char
230 void insert(char_type c);
232 void insert(docstring const & str);
234 /// FIXME: rename to something sensible showing difference to x_target()
235 /// in pixels from left of screen, set to current position if unset
237 /// set the targetX to x
238 void setTargetX(int x);
239 /// return targetX or -1 if unset
240 int x_target() const;
241 /// set targetX to current position
243 /// clear targetX, i.e. set it to -1
245 /// set offset to actual position - targetX
246 void updateTextTargetOffset();
247 /// distance between actual and targeted position during last up/down in text
248 int textTargetOffset() const;
250 /// access to normalized selection anchor
251 CursorSlice normalAnchor() const;
252 // FIXME: this can't be a const & and a const function because
253 // LFUN_TAB_* wants to move the real anchor.
254 /// access to real selection anchor
255 DocIterator & realAnchor();
256 /// sets anchor to cursor position
258 /// access to owning BufferView
259 BufferView & bv() const;
260 /// get some interesting description of top position
261 void info(odocstream & os) const;
262 /// are we in math mode (2), text mode (1) or unsure (0)?
264 /// reset cursor bottom to the beginning of the top inset
265 // (sort of 'chroot' environment...)
267 /// for spellchecking
268 void replaceWord(std::string const & replacestring);
270 * the event was not (yet) dispatched.
272 * Should only be called by an inset's doDispatch() method. It means:
273 * I, the doDispatch() method of InsetFoo, hereby declare that I am
274 * not able to handle that request and trust my parent will do the
275 * Right Thing (even if my getStatus partner said that I can do it).
276 * It is sort of a kludge that should be used only rarely...
278 void undispatched() const;
279 /// the event was already dispatched
280 void dispatched() const;
281 /// Set which screen update should be done
282 void screenUpdateFlags(Update::flags f) const;
283 /// Forces an updateBuffer() call
284 void forceBufferUpdate() const;
285 /// Removes any pending updateBuffer() call
286 void clearBufferUpdate() const;
287 /// Do we need to call updateBuffer()?
288 bool needBufferUpdate() const;
290 * don't call update() when done
292 * Should only be called by an inset's doDispatch() method. It means:
293 * I handled that request and I can reassure you that the screen does
294 * not need to be re-drawn and all entries in the coord cache stay
295 * valid (and there are no other things to put in the coord cache).
296 * This is a fairly rare event as well and only some optimization.
297 * Not using noScreenUpdate() should never be wrong.
299 void noScreenUpdate() const;
300 /// fix cursor in circumstances that should never happen.
301 /// \retval true if a fix occured.
303 /// Repopulate the slices insets from bottom to top. Useful
304 /// for stable iterators or Undo data.
308 friend std::ostream & operator<<(std::ostream & os, Cursor const & cur);
309 friend LyXErr & operator<<(LyXErr & os, Cursor const & cur);
316 /// makes sure the next operation will be stored
317 void finishUndo() const;
319 /// open a new group of undo operations. Groups can be nested.
320 void beginUndoGroup() const;
322 /// end the current undo group
323 void endUndoGroup() const;
325 /// The general case: prepare undo for an arbitrary range.
326 void recordUndo(UndoKind kind, pit_type from, pit_type to) const;
328 /// Convenience: prepare undo for the range between 'from' and cursor.
329 void recordUndo(UndoKind kind, pit_type from) const;
331 /// Convenience: prepare undo for the single paragraph or cell
332 /// containing the cursor
333 void recordUndo(UndoKind kind = ATOMIC_UNDO) const;
335 /// Convenience: prepare undo for the inset containing the cursor
336 void recordUndoInset(UndoKind kind = ATOMIC_UNDO,
337 Inset const * inset = 0) const;
339 /// Convenience: prepare undo for the whole buffer
340 void recordUndoFullDocument() const;
342 /// Convenience: prepare undo for the selected paragraphs or cells
343 void recordUndoSelection() const;
346 void checkBufferStructure();
348 /// hook for text input to maintain the "new born word"
349 void markNewWordPosition();
351 /// The position of the new born word
352 /// As the user is entering a word without leaving it
353 /// the result is not empty. When not in text mode
354 /// and after leaving the word the result is empty.
355 DocIterator newWord() const { return new_word_; }
361 DocIterator const & beforeDispatchCursor() const { return beforeDispatchCursor_; }
363 void saveBeforeDispatchPosXY();
366 /// validate the "new born word" position
367 void checkNewWordPosition();
368 /// clear the "new born word" position
369 void clearNewWordPosition();
375 mutable DispatchResult disp_;
377 * The target x position of the cursor. This is used for when
378 * we have text like :
380 * blah blah blah blah| blah blah blah
382 * blah blah blah blah blah blah
384 * When we move onto row 3, we would like to be vertically aligned
385 * with where we were in row 1, despite the fact that row 2 is
389 /// if a x_target cannot be hit exactly in a text, put the difference here
390 int textTargetOffset_;
391 /// the start of the new born word
392 DocIterator new_word_;
393 /// position before dispatch started
394 DocIterator beforeDispatchCursor_;
395 /// cursor screen coordinates before dispatch started
396 int beforeDispatchPosX_;
397 int beforeDispatchPosY_;
399 ///////////////////////////////////////////////////////////////////
401 // The part below is the non-integrated rest of the original math
402 // cursor. This should be either generalized for texted or moved
403 // back to the math insets.
405 ///////////////////////////////////////////////////////////////////
409 void insert(MathAtom const &);
411 void insert(MathData const &);
412 /// return false for empty math insets
414 /// return false for empty math insets
416 /// move the cursor up by sending an internal LFUN_UP
417 /// return true if fullscreen update is needed
419 /// move the cursor up by sending an internal LFUN_DOWN,
420 /// return true if fullscreen update is needed
422 /// whether the cursor is either at the first or last row
423 bool atFirstOrLastRow(bool up);
424 /// move up/down in a text inset, called for LFUN_UP/DOWN,
425 /// return true if successful, updateNeeded set to true if fullscreen
426 /// update is needed, otherwise it's not touched
427 bool upDownInText(bool up, bool & updateNeeded);
428 /// move up/down in math or any non text inset, call for LFUN_UP/DOWN
429 /// return true if successful
430 bool upDownInMath(bool up);
434 void plainInsert(MathAtom const & at);
436 void niceInsert(MathAtom const & at);
437 /// return the number of inserted array items
438 int niceInsert(docstring const & str, Parse::flags f = Parse::NORMAL,
441 /// in pixels from top of screen
442 void setScreenPos(int x, int y);
443 /// current offset in the top cell
445 /// interpret name a name of a macro. Returns true if
446 /// something got inserted.
447 bool macroModeClose();
448 /// are we currently typing the name of a macro?
449 bool inMacroMode() const;
450 /// get access to the macro we are currently typing
451 InsetMathUnknown * activeMacro();
452 /// get access to the macro we are currently typing
453 InsetMathUnknown const * activeMacro() const;
455 /// replace selected stuff with at, placing the former
456 // selection in given cell of atom
457 void handleNest(MathAtom const & at, int cell = 0);
459 bool isInside(Inset const *) const;
461 /// make sure cursor position is valid
462 /// FIXME: It does a subset of fixIfBroken. Maybe merge them?
464 /// mark current cursor trace for redraw
467 /// hack for reveal codes
470 /// injects content of a cell into parent
472 /// split font inset etc
473 void handleFont(std::string const & font);
475 /// display a message
476 void message(docstring const & msg) const;
477 /// display an error message
478 void errorMessage(docstring const & msg) const;
480 docstring getPossibleLabel() const;
482 /// the name of the macro we are currently inputting
483 docstring macroName();
484 /// where in the curent cell does the macro name start?
486 /// can we enter the inset?
487 bool openable(MathAtom const &) const;
489 Encoding const * getEncoding() const;
490 /// font at cursor position
491 Font getFont() const;
496 * Notifies all insets which appear in old, but not in cur. And then
497 * notify all insets which appear in cur, but not in old.
498 * Make sure that the cursor old is valid, i.e. all inset pointers
499 * point to valid insets! Use Cursor::fixIfBroken if necessary.
501 bool notifyCursorLeavesOrEnters(Cursor const & old, Cursor & cur);
506 #endif // LYXLCURSOR_H