]> git.lyx.org Git - features.git/blob - src/Cursor.h
8b76fb35d451fd94a93c29079b3ce69a808c84ed
[features.git] / src / Cursor.h
1 // -*- C++ -*-
2 /**
3  * \file Cursor.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author André Pönitz
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #ifndef LCURSOR_H
13 #define LCURSOR_H
14
15 #include "DispatchResult.h"
16 #include "DocIterator.h"
17 #include "Font.h"
18 #include "Undo.h"
19
20 #include <vector>
21
22
23 namespace lyx {
24
25 class Buffer;
26 class BufferView;
27 class FuncStatus;
28 class FuncRequest;
29 class Row;
30
31 // these should go
32 class InsetMathUnknown;
33 class Encoding;
34
35
36 /// The cursor class describes the position of a cursor within a document.
37
38 // The public inheritance should go in favour of a suitable data member
39 // (or maybe private inheritance) at some point of time.
40 class Cursor : public DocIterator {
41 public:
42         /// create the cursor of a BufferView
43         explicit Cursor(BufferView & bv);
44
45         /// dispatch from innermost inset upwards
46         void dispatch(FuncRequest const & cmd);
47         /// get the resut of the last dispatch
48         DispatchResult result() const;
49         /// add a new cursor slice
50         void push(Inset & inset);
51         /// add a new cursor slice, place cursor at front (move backwards)
52         void pushBackward(Inset & inset);
53         /// pop one level off the cursor
54         void pop();
55         /// pop one slice off the cursor stack and go backwards
56         bool popBackward();
57         /// pop one slice off the cursor stack and go forward
58         bool popForward();
59         /// make sure we are outside of given inset
60         void leaveInset(Inset const & inset);
61         /// sets cursor part
62         void setCursor(DocIterator const & it);
63
64         ///
65         void setCurrentFont();
66
67         //
68         // selection
69         //
70         /// selection active?
71         bool selection() const { return selection_; }
72         /// selection active?
73         bool & selection() { return selection_; }
74         /// do we have a multicell selection?
75         bool isMultiCell() const 
76                 { return selection_ && selBegin().idx() != selEnd().idx(); }
77         /// did we place the anchor?
78         bool mark() const { return mark_; }
79         /// did we place the anchor?
80         bool & mark() { return mark_; }
81         ///
82         void setSelection();
83         /// set selection at given position
84         void setSelection(DocIterator const & where, int n);
85         ///
86         void clearSelection();
87         /// access start of selection
88         CursorSlice selBegin() const;
89         /// access end of selection
90         CursorSlice selEnd() const;
91         /// access start of selection
92         DocIterator selectionBegin() const;
93         /// access start of selection
94         DocIterator selectionEnd() const;
95         /// FIXME: document this
96         bool selHandle(bool selecting);
97         ///
98         docstring selectionAsString(bool label) const;
99         ///
100         docstring currentState();
101
102         /// auto-correct mode
103         bool autocorrect() const { return autocorrect_; }
104         /// auto-correct mode
105         bool & autocorrect() { return autocorrect_; }
106         /// are we entering a macro name?
107         bool macromode() const { return macromode_; }
108         /// are we entering a macro name?
109         bool & macromode() { return macromode_; }
110         /// returns x,y position
111         void getPos(int & x, int & y) const;
112         /// return logical positions between which the cursor is situated
113         /**
114          * If the cursor is at the edge of a row, the position which is "over the 
115          * edge" will be returned as -1.
116          */
117         void getSurroundingPos(pos_type & left_pos, pos_type & right_pos);
118         /// the row in the paragraph we're in
119         Row const & textRow() const;
120
121         //
122         // common part
123         //
124         /// move one step backwards
125         bool posBackward();
126         /// move one step forward
127         bool posForward();
128         /// move visually one step to the right
129         /**
130          * @note: This method may move into an inset unless skip_inset == true.
131          * @note: This method may move into a new paragraph.
132          * @note: This method may move out of the current slice.
133          * @return: true if moved, false if not moved
134          */
135         bool posVisRight(bool skip_inset = false);
136         /// move visually one step to the left
137         /**
138          * @note: This method may move into an inset unless skip_inset == true.
139          * @note: This method may move into a new paragraph.
140          * @note: This method may move out of the current slice.
141          * @return: true if moved, false if not moved
142          */
143         bool posVisLeft(bool skip_inset = false);
144         /// move visually to next/previous row
145         /**
146          * Assuming we were to keep moving left (right) from the current cursor
147          * position, place the cursor at the rightmost (leftmost) edge of the 
148          * new row to which we would move according to visual-mode cursor movement.
149          * This could be either the next or the previous row, depending on the
150          * direction in which we're moving, and whether we're in an LTR or RTL 
151          * paragraph. 
152          * @note: The new position may even be in a new paragraph.
153          * @note: This method will not move out of the current slice.
154          * @return: false if not moved (no more rows to move to in given direction)
155          * @return: true if moved
156          */
157         bool posVisToNewRow(bool movingLeft);
158         /// move to right or left extremity of the current row
159         void posVisToRowExtremity(bool left);
160
161         /// insert an inset
162         void insert(Inset *);
163         /// insert a single char
164         void insert(char_type c);
165         /// insert a string
166         void insert(docstring const & str);
167
168         /// FIXME: rename to something sensible showing difference to x_target()
169         /// in pixels from left of screen, set to current position if unset
170         int targetX() const;
171         /// set the targetX to x
172         void setTargetX(int x);
173         /// return targetX or -1 if unset
174         int x_target() const;
175         /// set targetX to current position
176         void setTargetX();
177         /// clear targetX, i.e. set it to -1
178         void clearTargetX();
179         /// set offset to actual position - targetX
180         void updateTextTargetOffset();
181         /// distance between actual and targeted position during last up/down in text
182         int textTargetOffset() const;
183
184         /// access to normalized selection anchor
185         CursorSlice anchor() const;
186         /// sets anchor to cursor position
187         void resetAnchor();
188         /// access to owning BufferView
189         BufferView & bv() const;
190         /// access to owning Buffer
191         Buffer & buffer() const;
192         /// get some interesting description of top position
193         void info(odocstream & os) const;
194         /// are we in math mode (2), text mode (1) or unsure (0)?
195         int currentMode();
196         /// reset cursor bottom to the beginning of the given inset
197         // (sort of 'chroot' environment...)
198         void reset(Inset &);
199         /// for spellchecking
200         void replaceWord(std::string const & replacestring);
201         /**
202          * the event was not (yet) dispatched.
203          *
204          * Should only be called by an inset's doDispatch() method. It means:
205          * I, the doDispatch() method of InsetFoo, hereby declare that I am
206          * not able to handle that request and trust my parent will do the
207          * Right Thing (even if my getStatus partner said that I can do it).
208          * It is sort of a kludge that should be used only rarely...
209          */
210         void undispatched();
211         /// the event was already dispatched
212         void dispatched();
213         /// Set which update should be done
214         void updateFlags(Update::flags f);
215         /**
216          * don't call update() when done
217          *
218          * Should only be called by an inset's doDispatch() method. It means:
219          * I handled that request and I can reassure you that the screen does
220          * not need to be re-drawn and all entries in the coord cache stay
221          * valid (and there are no other things to put in the coord cache).
222          * This is a fairly rare event as well and only some optimization.
223          * Not using noUpdate() should never be wrong.
224          */
225         void noUpdate();
226         /// fix cursor in circumstances that should never happen.
227         /// \retval true if a fix occured.
228         bool fixIfBroken();
229
230         /// output
231         friend std::ostream & operator<<(std::ostream & os, Cursor const & cur);
232         friend LyXErr & operator<<(LyXErr & os, Cursor const & cur);
233
234         ///
235         bool textUndo();
236         ///
237         bool textRedo();
238
239         /// makes sure the next operation will be stored
240         void finishUndo();
241
242         /// The general case: prepare undo for an arbitrary range.
243         void recordUndo(UndoKind kind, pit_type from, pit_type to);
244
245         /// Convenience: prepare undo for the range between 'from' and cursor.
246         void recordUndo(UndoKind kind, pit_type from);
247
248         /// Convenience: prepare undo for the single paragraph or cell
249         /// containing the cursor
250         void recordUndo(UndoKind kind = ATOMIC_UNDO);
251
252         /// Convenience: prepare undo for the inset containing the cursor
253         void recordUndoInset(UndoKind kind = ATOMIC_UNDO);
254
255         /// Convenience: prepare undo for the whole buffer
256         void recordUndoFullDocument();
257
258         /// Convenience: prepare undo for the selected paragraphs or cells
259         void recordUndoSelection();
260
261         ///
262         void checkBufferStructure();
263
264 public:
265         ///
266         BufferView * bv_;
267 //private:
268         /// the anchor position
269         DocIterator anchor_;
270         
271         ///
272         DispatchResult disp_;
273         ///
274         DocIterator const & beforeDispatchCursor() { return beforeDispatchCursor_; }
275         
276 private:
277         /**
278          * The target x position of the cursor. This is used for when
279          * we have text like :
280          *
281          * blah blah blah blah| blah blah blah
282          * blah blah blah
283          * blah blah blah blah blah blah
284          *
285          * When we move onto row 3, we would like to be vertically aligned
286          * with where we were in row 1, despite the fact that row 2 is
287          * shorter than x()
288          */
289         int x_target_;
290         /// if a x_target cannot be hit exactly in a text, put the difference here
291         int textTargetOffset_;
292         /// do we have a selection?
293         bool selection_;
294         /// are we on the way to get one?
295         bool mark_;
296         /// If true, we are behind the previous char, otherwise we are in front
297         // of the next char. This only make a difference when we are in front
298         // of a big inset spanning a whole row and computing coordinates for
299         // displaying the cursor.
300         bool logicalpos_;
301         /// position before dispatch started
302         DocIterator beforeDispatchCursor_;
303
304 // FIXME: make them private.
305 public:
306         /// the current font settings
307         Font current_font;
308         /// the current font
309         Font real_current_font;
310
311 private:
312
313         //
314         // math specific stuff that could be promoted to "global" later
315         //
316         /// do we allow autocorrection
317         bool autocorrect_;
318         /// are we entering a macro name?
319         bool macromode_;
320
321
322 ///////////////////////////////////////////////////////////////////
323 //
324 // The part below is the non-integrated rest of the original math
325 // cursor. This should be either generalized for texted or moved
326 // back to the math insets.
327 //
328 ///////////////////////////////////////////////////////////////////
329
330 public:
331         ///
332         void insert(MathAtom const &);
333         ///
334         void insert(MathData const &);
335         /// return false for empty math insets
336         bool erase();
337         /// return false for empty math insets
338         bool backspace();
339         /// move the cursor up by sending an internal LFUN_UP
340         /// return true if fullscreen update is needed
341         bool up();
342         /// move the cursor up by sending an internal LFUN_DOWN,
343         /// return true if fullscreen update is needed
344         bool down();
345         /// move up/down in a text inset, called for LFUN_UP/DOWN,
346         /// return true if successful, updateNeeded set to true if fullscreen
347         /// update is needed, otherwise it's not touched
348         bool upDownInText(bool up, bool & updateNeeded);
349         /// move up/down in math or any non text inset, call for LFUN_UP/DOWN
350         /// return true if successful
351         bool upDownInMath(bool up);
352         ///
353         void plainErase();
354         ///
355         void plainInsert(MathAtom const & at);
356         ///
357         void niceInsert(MathAtom const & at);
358         ///
359         void niceInsert(docstring const & str);
360
361         /// in pixels from top of screen
362         void setScreenPos(int x, int y);
363         /// current offset in the top cell
364
365         /// interpret name a name of a macro. Returns true if
366         /// something got inserted.
367         bool macroModeClose();
368         /// are we currently typing the name of a macro?
369         bool inMacroMode() const;
370         /// get access to the macro we are currently typing
371         InsetMathUnknown * activeMacro();
372         /// get access to the macro we are currently typing
373         InsetMathUnknown const * activeMacro() const;
374
375         /// replace selected stuff with at, placing the former
376         // selection in given cell of atom
377         void handleNest(MathAtom const & at, int cell = 0);
378         ///
379         bool isInside(Inset const *) const;
380
381         /// make sure cursor position is valid
382         /// FIXME: It does a subset of fixIfBroken. Maybe merge them?
383         void normalize();
384         /// mark current cursor trace for redraw
385         void touch();
386
387         /// hack for reveal codes
388         void markInsert();
389         void markErase();
390         /// injects content of a cell into parent
391         void pullArg();
392         /// split font inset etc
393         void handleFont(std::string const & font);
394
395         /// display a message
396         void message(docstring const & msg) const;
397         /// display an error message
398         void errorMessage(docstring const & msg) const;
399         ///
400         docstring getPossibleLabel();
401
402         /// the name of the macro we are currently inputting
403         docstring macroName();
404         /// where in the curent cell does the macro name start?
405         int macroNamePos();
406         /// can we enter the inset?
407         bool openable(MathAtom const &) const;
408         ///
409         Encoding const * getEncoding() const;
410         /// font at cursor position
411         Font getFont() const;
412 };
413
414
415 /**
416  * Notifies all insets which appear in old, but not in cur. Make
417  * Sure that the cursor old is valid, i.e. all inset pointers
418  * point to valid insets! Use Cursor::fixIfBroken if necessary.
419  */
420 bool notifyCursorLeaves(Cursor const & old, Cursor & cur);
421
422
423 } // namespace lyx
424
425 #endif // LYXLCURSOR_H