]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
move cursor related data fro LyXText to new strcut TextCursor
[lyx.git] / src / lyxtext.h
1 // -*- C++ -*-
2 /**
3  * \file lyxtext.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author unknown
8  * \author Lars Gullik Bjønnes
9  * \author John Levon
10  *
11  * Full author contact details are available in file CREDITS
12  */
13
14 #ifndef LYXTEXT_H
15 #define LYXTEXT_H
16
17 #include "lyxfont.h"
18 #include "lyxcursor.h"
19 #include "layout.h"
20 #include "LColor.h"
21 #include "insets/inset.h"
22 #include "RowList.h"
23 #include "bufferview_funcs.h"
24 #include "textcursor.h"
25
26 class Buffer;
27 class BufferParams;
28 class BufferView;
29 class InsetText;
30 class Paragraph;
31 class Row;
32 class Spacing;
33 class UpdatableInset;
34 class VSpace;
35 class WordLangTuple;
36 class ParagraphList;
37
38
39 /**
40   This class holds the mapping between buffer paragraphs and screen rows.
41   */
42
43 // The inheritance from TextCursor should go. It's just there to ease
44 // transition...
45 class LyXText : public TextCursor {
46 public:
47         /// what repainting is needed
48         enum refresh_status {
49                 /// no repaint is needed
50                 REFRESH_NONE = 0,
51                 /// the refresh_row needs repainting
52                 REFRESH_ROW = 1,
53                 /// everything from refresh_y downwards needs repainting
54                 REFRESH_AREA = 2
55         };
56
57         ///
58         enum word_location {
59                 // the word around the cursor, only if the cursor is
60                 //not at a boundary
61                 WHOLE_WORD_STRICT,
62                 // the word around the cursor
63                 WHOLE_WORD,
64                 /// the word begining from the cursor position
65                 PARTIAL_WORD,
66                 /// the word around the cursor or before the cursor
67                 PREVIOUS_WORD,
68                 /// the next word (not yet used)
69                 NEXT_WORD
70         };
71
72         /// Constructor
73         LyXText(BufferView *);
74         /// sets inset as owner
75         LyXText(BufferView *, InsetText *);
76
77         void init(BufferView *, bool reinit = false);
78         ///
79         int height;
80         ///
81         unsigned int width;
82         /// the current font settings
83         LyXFont current_font;
84         /// the current font
85         LyXFont real_current_font;
86 private:
87         /** the 'anchor' row: the position of this row remains constant
88          *  with respect to the top of the screen
89          */
90         RowList::iterator anchor_row_;
91         /** the pixel offset with respect to this row of top_y
92          */
93         int anchor_row_offset_;
94 public:
95         /// update all cached row positions
96         void updateRowPositions();
97         /// get the y coord. of the top of the screen (relative to doc start)
98         int top_y() const;
99         /// set the y coord. of the top of the screen (relative to doc start)
100         void top_y(int newy);
101         /// set the anchoring row. top_y will be computed relative to this
102         void anchor_row(RowList::iterator rit);
103         ///
104         InsetText * inset_owner;
105         ///
106         UpdatableInset * the_locking_inset;
107
108         ///
109         int getRealCursorX() const;
110         ///
111         LyXFont const getFont(Buffer const *, ParagraphList::iterator pit,
112                 lyx::pos_type pos) const;
113         ///
114         LyXFont const getLayoutFont(Buffer const *,
115                                     ParagraphList::iterator pit) const;
116         ///
117         LyXFont const getLabelFont(Buffer const *,
118                                    ParagraphList::iterator pit) const;
119         ///
120         void setCharFont(Buffer const *, ParagraphList::iterator pit,
121                          lyx::pos_type pos, LyXFont const & font);
122         void setCharFont(ParagraphList::iterator pit,
123                          lyx::pos_type pos,
124                          LyXFont const & font, bool toggleall);
125
126         ///
127         void breakAgainOneRow(RowList::iterator rit);
128         /// what you expect when pressing <enter> at cursor position
129         void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
130
131         /** set layout over selection and make a total rebreak of
132           those paragraphs
133           */
134         ParagraphList::iterator
135         setLayout(LyXCursor & actual_cursor,
136                   LyXCursor & selection_start,
137                   LyXCursor & selection_end,
138                   string const & layout);
139         ///
140         void setLayout(string const & layout);
141
142         /**
143          * Increase or decrease the nesting depth of the selected paragraph(s)
144          * if test_only, don't change any depths. Returns whether something
145          * (would have) changed
146          */
147         bool changeDepth(bv_funcs::DEPTH_CHANGE type, bool test_only);
148
149         /// get the depth at current cursor position
150         int getDepth() const;
151
152         /** set font over selection and make a total rebreak of those
153           paragraphs.
154           toggleall defaults to false.
155           */
156         void setFont(LyXFont const &, bool toggleall = false);
157
158         /** deletes and inserts again all paragaphs between the cursor
159           and the specified par. The Cursor is needed to set the refreshing
160           parameters.
161           This function is needed after SetLayout and SetFont etc.
162           */
163         void redoParagraphs(LyXCursor const & cursor,
164                             ParagraphList::iterator endpit);
165         ///
166         void redoParagraph();
167
168         ///
169         void toggleFree(LyXFont const &, bool toggleall = false);
170
171         ///
172         string getStringToIndex();
173
174         /** recalculates the heights of all previous rows of the
175             specified paragraph.  needed, if the last characters font
176             has changed.
177             */
178         void redoHeightOfParagraph();
179
180         /** insert a character, moves all the following breaks in the
181           same Paragraph one to the right and make a little rebreak
182           */
183         void insertChar(char c);
184         ///
185         void insertInset(Inset * inset);
186
187         /// Completes the insertion with a rebreak from 'need_break_row' on
188         void partialRebreak();
189         /// a full rebreak of the whole text
190         void fullRebreak();
191
192         ///
193         RowList::iterator need_break_row;
194
195         /// clear any pending paints
196         void clearPaint();
197
198         /**
199          * Mark position y as the starting point for a repaint
200          */
201         void postPaint(int start_y);
202
203         /**
204          * Mark the given row at position y as needing a repaint.
205          */
206         void postRowPaint(RowList::iterator rit, int start_y);
207
208         ///
209         Inset::RESULT dispatch(FuncRequest const & cmd);
210
211         BufferView * bv();
212
213         BufferView * bv() const;
214
215         friend class LyXScreen;
216
217         /**
218          * Return the status. This represents what repaints are
219          * pending after some operation (e.g. inserting a char).
220          */
221         refresh_status refreshStatus() const;
222
223 private:
224         /**
225          * The pixel y position from which to repaint the screen.
226          * The position is absolute along the height of outermost
227          * lyxtext (I think). REFRESH_AREA and REFRESH_ROW
228          * repaints both use this as a starting point (if it's within
229          * the viewable portion of the lyxtext).
230          */
231         int refresh_y;
232         /**
233          * The row from which to repaint the screen, used by screen.c.
234          * This must be set if the pending update is REFRESH_ROW.
235          * It doesn't make any difference for REFRESH_AREA.
236          */
237         RowList::iterator refresh_row;
238
239         refresh_status refresh_status_;
240
241         /// only the top-level LyXText has this non-zero
242         BufferView * bv_owner;
243
244         /// returns a pointer to a specified row.
245         RowList::iterator
246         getRow(ParagraphList::iterator pit, lyx::pos_type pos) const;
247 public:
248         /// returns a pointer cursor row
249         RowList::iterator getRow(LyXCursor const & cursor) const;
250         /// convenience
251         RowList::iterator cursorRow() const;
252         
253         /** returns a pointer to the row near the specified y-coordinate
254           (relative to the whole text). y is set to the real beginning
255           of this row
256           */
257         RowList::iterator getRowNearY(int & y) const;
258
259         /** returns the column near the specified x-coordinate of the row
260          x is set to the real beginning of this column
261          */
262         lyx::pos_type getColumnNearX(RowList::iterator rit,
263                                      int & x, bool & boundary) const;
264
265         /** returns a pointer to a specified row. y is set to the beginning
266          of the row
267          */
268         RowList::iterator
269         getRow(ParagraphList::iterator pit, lyx::pos_type pos, int & y) const;
270
271         RowList & rows() const {
272                 return rowlist_;
273         }
274
275         
276         /// need the selection cursor:
277         void setSelection();
278         ///
279         void clearSelection();
280         ///
281         string const selectionAsString(Buffer const *, bool label) const;
282
283         /// select the word we need depending on word_location
284         void getWord(LyXCursor & from, LyXCursor & to,
285                      word_location const);
286         /// just selects the word the cursor is in
287         void selectWord(word_location const);
288         /// returns the inset at cursor (if it exists), 0 otherwise
289         Inset * getInset() const;
290
291         /// accept selected change
292         void acceptChange();
293
294         /// reject selected change
295         void rejectChange();
296
297         /** 'selects" the next word, where the cursor is not in
298          and returns this word as string. THe cursor will be moved
299          to the beginning of this word.
300          With SelectSelectedWord can this be highlighted really
301          */
302         WordLangTuple const selectNextWordToSpellcheck(float & value);
303         ///
304         void selectSelectedWord();
305         /// returns true if par was empty and was removed
306         bool setCursor(ParagraphList::iterator pit,
307                        lyx::pos_type pos,
308                        bool setfont = true,
309                        bool boundary = false);
310         ///
311         void setCursor(LyXCursor &, ParagraphList::iterator pit,
312                        lyx::pos_type pos,
313                        bool boundary = false);
314         ///
315         void setCursorIntern(ParagraphList::iterator pit,
316                              lyx::pos_type pos,
317                              bool setfont = true,
318                              bool boundary = false);
319         ///
320         void setCurrentFont();
321
322         ///
323         bool isBoundary(Buffer const *, Paragraph const & par,
324                         lyx::pos_type pos) const;
325         ///
326         bool isBoundary(Buffer const *, Paragraph const & par,
327                          lyx::pos_type pos,
328                          LyXFont const & font) const;
329
330         ///
331         void setCursorFromCoordinates(int x, int y);
332         ///
333         void setCursorFromCoordinates(LyXCursor &,
334                                       int x, int y);
335         ///
336         void cursorUp(bool selecting = false);
337         ///
338         void cursorDown(bool selecting = false);
339         ///
340         void cursorLeft(bool internal = true);
341         ///
342         void cursorRight(bool internal = true);
343         ///
344         void cursorLeftOneWord();
345         ///
346         void cursorRightOneWord();
347         ///
348         void cursorUpParagraph();
349         ///
350         void cursorDownParagraph();
351         ///
352         void cursorHome();
353         ///
354         void cursorEnd();
355         ///
356         void cursorPrevious();
357         ///
358         void cursorNext();
359         ///
360         void cursorTop();
361         ///
362         void cursorBottom();
363         ///
364         void Delete();
365         ///
366         void backspace();
367         ///
368         bool selectWordWhenUnderCursor(word_location);
369         ///
370         enum TextCase {
371                 ///
372                 text_lowercase = 0,
373                 ///
374                 text_capitalization = 1,
375                 ///
376                 text_uppercase = 2
377         };
378         /// Change the case of the word at cursor position.
379         void changeCase(TextCase action);
380
381         ///
382         void toggleInset();
383         ///
384         void cutSelection(bool doclear = true, bool realcut = true);
385         ///
386         void copySelection();
387         ///
388         void pasteSelection(size_t sel_index = 0);
389
390         /** the DTP switches for paragraphs. LyX will store the top settings
391          always in the first physical paragraph, the bottom settings in the
392          last. When a paragraph is broken, the top settings rest, the bottom
393          settings are given to the new one. So I can make shure, they do not
394          duplicate themself (and you cannnot make dirty things with them! )
395          */
396         void setParagraph(bool line_top, bool line_bottom,
397                           bool pagebreak_top, bool pagebreak_bottom,
398                           VSpace const & space_top,
399                           VSpace const & space_bottom,
400                           Spacing const & spacing,
401                           LyXAlignment align,
402                           string const & labelwidthstring,
403                           bool noindent);
404
405         /* these things are for search and replace */
406
407         /**
408          * Sets the selection from the current cursor position to length
409          * characters to the right. No safety checks.
410          */
411         void setSelectionRange(lyx::pos_type length);
412
413         /** simple replacing. The font of the first selected character
414           is used
415           */
416         void replaceSelectionWithString(string const & str);
417
418         /// needed to insert the selection
419         void insertStringAsLines(string const & str);
420         /// needed to insert the selection
421         void insertStringAsParagraphs(string const & str);
422
423         /// Find next inset of some specified type.
424         bool gotoNextInset(std::vector<Inset::Code> const & codes,
425                            string const & contents = string());
426         ///
427         void gotoInset(std::vector<Inset::Code> const & codes,
428                        bool same_content);
429         ///
430         void gotoInset(Inset::Code code, bool same_content);
431         ///
432
433         /* for the greater insets */
434
435         /// returns false if inset wasn't found
436         bool updateInset(Inset *);
437         ///
438         void checkParagraph(ParagraphList::iterator pit, lyx::pos_type pos);
439         ///
440         int workWidth() const;
441         /// returns width of row containing inset
442         int workWidth(Inset const * inset) const;
443
444         ///
445         void computeBidiTables(Buffer const *, RowList::iterator row) const;
446         /// Maps positions in the visual string to positions in logical string.
447         lyx::pos_type log2vis(lyx::pos_type pos) const;
448         /// Maps positions in the logical string to positions in visual string.
449         lyx::pos_type vis2log(lyx::pos_type pos) const;
450         ///
451         lyx::pos_type bidi_level(lyx::pos_type pos) const;
452         ///
453         bool bidi_InRange(lyx::pos_type pos) const;
454 private:
455         ///
456         mutable RowList rowlist_;
457         ///
458         void cursorLeftOneWord(LyXCursor &);
459
460         ///
461         float getCursorX(RowList::iterator rit, lyx::pos_type pos,
462                          lyx::pos_type last, bool boundary) const;
463         /// used in setlayout
464         void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
465
466         /** forces the redrawing of a paragraph. Needed when manipulating a
467             right address box
468             */
469         void redoDrawingOfParagraph(LyXCursor const & cursor);
470
471         /// removes the row and reset the touched counters
472         void removeRow(RowList::iterator rit);
473
474         /// remove all following rows of the paragraph of the specified row.
475         void removeParagraph(RowList::iterator rit);
476
477         /// insert the specified paragraph behind the specified row
478         void insertParagraph(ParagraphList::iterator pit,
479                              RowList::iterator rowit);
480
481         /** appends  the implizit specified paragraph behind the specified row,
482          * start at the implizit given position */
483         void appendParagraph(RowList::iterator rowit);
484
485         ///
486         void breakAgain(RowList::iterator rit);
487         /// Calculate and set the height of the row
488         void setHeightOfRow(RowList::iterator rit);
489
490         // fix the cursor `cur' after a characters has been deleted at `where'
491         // position. Called by deleteEmptyParagraphMechanism
492         void fixCursorAfterDelete(LyXCursor & cur,
493                                   LyXCursor const & where);
494
495         /// delete double space (false) or empty paragraphs (true) around old_cursor
496         bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor);
497
498 public:
499         /** Updates all counters starting BEHIND the row. Changed paragraphs
500          * with a dynamic left margin will be rebroken. */
501         void updateCounters();
502         ///
503         void update();
504         /**
505          * Returns an inset if inset was hit, or 0 if not.
506          * If hit, the coordinates are changed relative to the inset.
507          */
508         Inset * checkInsetHit(int & x, int & y);
509
510         ///
511         int singleWidth(ParagraphList::iterator pit,
512                 lyx::pos_type pos) const;
513         ///
514         int singleWidth(ParagraphList::iterator pit,
515                 lyx::pos_type pos, char c) const;
516
517         /// return the color of the canvas
518         LColor::color backgroundColor() const;
519
520         ///
521         mutable bool bidi_same_direction;
522
523         unsigned char transformChar(unsigned char c, Paragraph const & par,
524                                     lyx::pos_type pos) const;
525
526         /**
527          * Returns the left beginning of the text.
528          * This information cannot be taken from the layout object, because
529          * in LaTeX the beginning of the text fits in some cases
530          * (for example sections) exactly the label-width.
531          */
532         int leftMargin(Row const & row) const;
533         ///
534         int rightMargin(Buffer const &, Row const & row) const;
535
536         /** this calculates the specified parameters. needed when setting
537          * the cursor and when creating a visible row */
538         void prepareToPrint(RowList::iterator row, float & x,
539                             float & fill_separator,
540                             float & fill_hfill,
541                             float & fill_label_hfill,
542                             bool bidi = true) const;
543
544 private:
545         ///
546         void setCounter(Buffer const *, ParagraphList::iterator pit);
547         ///
548         void deleteWordForward();
549         ///
550         void deleteWordBackward();
551         ///
552         void deleteLineForward();
553
554         /*
555          * some low level functions
556          */
557
558
559         /// return the pos value *before* which a row should break.
560         /// for example, the pos at which IsNewLine(pos) == true
561         lyx::pos_type rowBreakPoint(Row const & row) const;
562
563         /// returns the minimum space a row needs on the screen in pixel
564         int fill(RowList::iterator row, int workwidth) const;
565
566         /**
567          * returns the minimum space a manual label needs on the
568          * screen in pixels
569          */
570         int labelFill(Row const & row) const;
571
572         /// FIXME
573         int labelEnd(Row const & row) const;
574
575         ///
576         mutable std::vector<lyx::pos_type> log2vis_list;
577         ///
578         mutable std::vector<lyx::pos_type> vis2log_list;
579         ///
580         mutable std::vector<lyx::pos_type> bidi_levels;
581         ///
582         mutable lyx::pos_type bidi_start;
583         ///
584         mutable lyx::pos_type bidi_end;
585
586         ///
587         void charInserted();
588 public:
589         //
590         // special owner functions
591         ///
592         ParagraphList & ownerParagraphs() const;
593
594         /// return true if this is owned by an inset.
595         bool isInInset() const;
596
597 private:
598         /** Cursor related data.
599           Later this variable has to be removed. There should be now internal
600           cursor in a text */
601         ///
602         ///TextCursor cursor_;
603 };
604
605 /// return the default height of a row in pixels, considering font zoom
606 extern int defaultRowHeight();
607
608 #endif // LYXTEXT_H