]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
move some selection related stuff over to textcursor.C
[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         /// select the word we need depending on word_location
282         void getWord(LyXCursor & from, LyXCursor & to,
283                      word_location const);
284         /// just selects the word the cursor is in
285         void selectWord(word_location const);
286         /// returns the inset at cursor (if it exists), 0 otherwise
287         Inset * getInset() const;
288
289         /// accept selected change
290         void acceptChange();
291
292         /// reject selected change
293         void rejectChange();
294
295         /** 'selects" the next word, where the cursor is not in
296          and returns this word as string. THe cursor will be moved
297          to the beginning of this word.
298          With SelectSelectedWord can this be highlighted really
299          */
300         WordLangTuple const selectNextWordToSpellcheck(float & value);
301         ///
302         void selectSelectedWord();
303         /// returns true if par was empty and was removed
304         bool setCursor(ParagraphList::iterator pit,
305                        lyx::pos_type pos,
306                        bool setfont = true,
307                        bool boundary = false);
308         ///
309         void setCursor(LyXCursor &, ParagraphList::iterator pit,
310                        lyx::pos_type pos,
311                        bool boundary = false);
312         ///
313         void setCursorIntern(ParagraphList::iterator pit,
314                              lyx::pos_type pos,
315                              bool setfont = true,
316                              bool boundary = false);
317         ///
318         void setCurrentFont();
319
320         ///
321         bool isBoundary(Buffer const *, Paragraph const & par,
322                         lyx::pos_type pos) const;
323         ///
324         bool isBoundary(Buffer const *, Paragraph const & par,
325                          lyx::pos_type pos,
326                          LyXFont const & font) const;
327
328         ///
329         void setCursorFromCoordinates(int x, int y);
330         ///
331         void setCursorFromCoordinates(LyXCursor &,
332                                       int x, int y);
333         ///
334         void cursorUp(bool selecting = false);
335         ///
336         void cursorDown(bool selecting = false);
337         ///
338         void cursorLeft(bool internal = true);
339         ///
340         void cursorRight(bool internal = true);
341         ///
342         void cursorLeftOneWord();
343         ///
344         void cursorRightOneWord();
345         ///
346         void cursorUpParagraph();
347         ///
348         void cursorDownParagraph();
349         ///
350         void cursorHome();
351         ///
352         void cursorEnd();
353         ///
354         void cursorPrevious();
355         ///
356         void cursorNext();
357         ///
358         void cursorTop();
359         ///
360         void cursorBottom();
361         ///
362         void Delete();
363         ///
364         void backspace();
365         ///
366         bool selectWordWhenUnderCursor(word_location);
367         ///
368         enum TextCase {
369                 ///
370                 text_lowercase = 0,
371                 ///
372                 text_capitalization = 1,
373                 ///
374                 text_uppercase = 2
375         };
376         /// Change the case of the word at cursor position.
377         void changeCase(TextCase action);
378
379         ///
380         void toggleInset();
381         ///
382         void cutSelection(bool doclear = true, bool realcut = true);
383         ///
384         void copySelection();
385         ///
386         void pasteSelection(size_t sel_index = 0);
387
388         /** the DTP switches for paragraphs. LyX will store the top settings
389          always in the first physical paragraph, the bottom settings in the
390          last. When a paragraph is broken, the top settings rest, the bottom
391          settings are given to the new one. So I can make shure, they do not
392          duplicate themself (and you cannnot make dirty things with them! )
393          */
394         void setParagraph(bool line_top, bool line_bottom,
395                           bool pagebreak_top, bool pagebreak_bottom,
396                           VSpace const & space_top,
397                           VSpace const & space_bottom,
398                           Spacing const & spacing,
399                           LyXAlignment align,
400                           string const & labelwidthstring,
401                           bool noindent);
402
403         /* these things are for search and replace */
404
405         /**
406          * Sets the selection from the current cursor position to length
407          * characters to the right. No safety checks.
408          */
409         void setSelectionRange(lyx::pos_type length);
410
411         /** simple replacing. The font of the first selected character
412           is used
413           */
414         void replaceSelectionWithString(string const & str);
415
416         /// needed to insert the selection
417         void insertStringAsLines(string const & str);
418         /// needed to insert the selection
419         void insertStringAsParagraphs(string const & str);
420
421         /// Find next inset of some specified type.
422         bool gotoNextInset(std::vector<Inset::Code> const & codes,
423                            string const & contents = string());
424         ///
425         void gotoInset(std::vector<Inset::Code> const & codes,
426                        bool same_content);
427         ///
428         void gotoInset(Inset::Code code, bool same_content);
429         ///
430
431         /* for the greater insets */
432
433         /// returns false if inset wasn't found
434         bool updateInset(Inset *);
435         ///
436         void checkParagraph(ParagraphList::iterator pit, lyx::pos_type pos);
437         ///
438         int workWidth() const;
439         /// returns width of row containing inset
440         int workWidth(Inset const * inset) const;
441
442         ///
443         void computeBidiTables(Buffer const *, RowList::iterator row) const;
444         /// Maps positions in the visual string to positions in logical string.
445         lyx::pos_type log2vis(lyx::pos_type pos) const;
446         /// Maps positions in the logical string to positions in visual string.
447         lyx::pos_type vis2log(lyx::pos_type pos) const;
448         ///
449         lyx::pos_type bidi_level(lyx::pos_type pos) const;
450         ///
451         bool bidi_InRange(lyx::pos_type pos) const;
452 private:
453         ///
454         mutable RowList rowlist_;
455         ///
456         void cursorLeftOneWord(LyXCursor &);
457
458         ///
459         float getCursorX(RowList::iterator rit, lyx::pos_type pos,
460                          lyx::pos_type last, bool boundary) const;
461         /// used in setlayout
462         void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
463
464         /** forces the redrawing of a paragraph. Needed when manipulating a
465             right address box
466             */
467         void redoDrawingOfParagraph(LyXCursor const & cursor);
468
469         /// removes the row and reset the touched counters
470         void removeRow(RowList::iterator rit);
471
472         /// remove all following rows of the paragraph of the specified row.
473         void removeParagraph(RowList::iterator rit);
474
475         /// insert the specified paragraph behind the specified row
476         void insertParagraph(ParagraphList::iterator pit,
477                              RowList::iterator rowit);
478
479         /** appends  the implizit specified paragraph behind the specified row,
480          * start at the implizit given position */
481         void appendParagraph(RowList::iterator rowit);
482
483         ///
484         void breakAgain(RowList::iterator rit);
485         /// Calculate and set the height of the row
486         void setHeightOfRow(RowList::iterator rit);
487
488         // fix the cursor `cur' after a characters has been deleted at `where'
489         // position. Called by deleteEmptyParagraphMechanism
490         void fixCursorAfterDelete(LyXCursor & cur,
491                                   LyXCursor const & where);
492
493         /// delete double space (false) or empty paragraphs (true) around old_cursor
494         bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor);
495
496 public:
497         /** Updates all counters starting BEHIND the row. Changed paragraphs
498          * with a dynamic left margin will be rebroken. */
499         void updateCounters();
500         ///
501         void update();
502         /**
503          * Returns an inset if inset was hit, or 0 if not.
504          * If hit, the coordinates are changed relative to the inset.
505          */
506         Inset * checkInsetHit(int & x, int & y);
507
508         ///
509         int singleWidth(ParagraphList::iterator pit,
510                 lyx::pos_type pos) const;
511         ///
512         int singleWidth(ParagraphList::iterator pit,
513                 lyx::pos_type pos, char c) const;
514
515         /// return the color of the canvas
516         LColor::color backgroundColor() const;
517
518         ///
519         mutable bool bidi_same_direction;
520
521         unsigned char transformChar(unsigned char c, Paragraph const & par,
522                                     lyx::pos_type pos) const;
523
524         /**
525          * Returns the left beginning of the text.
526          * This information cannot be taken from the layout object, because
527          * in LaTeX the beginning of the text fits in some cases
528          * (for example sections) exactly the label-width.
529          */
530         int leftMargin(Row const & row) const;
531         ///
532         int rightMargin(Buffer const &, Row const & row) const;
533
534         /** this calculates the specified parameters. needed when setting
535          * the cursor and when creating a visible row */
536         void prepareToPrint(RowList::iterator row, float & x,
537                             float & fill_separator,
538                             float & fill_hfill,
539                             float & fill_label_hfill,
540                             bool bidi = true) const;
541
542 private:
543         ///
544         void setCounter(Buffer const *, ParagraphList::iterator pit);
545         ///
546         void deleteWordForward();
547         ///
548         void deleteWordBackward();
549         ///
550         void deleteLineForward();
551
552         /*
553          * some low level functions
554          */
555
556
557         /// return the pos value *before* which a row should break.
558         /// for example, the pos at which IsNewLine(pos) == true
559         lyx::pos_type rowBreakPoint(Row const & row) const;
560
561         /// returns the minimum space a row needs on the screen in pixel
562         int fill(RowList::iterator row, int workwidth) const;
563
564         /**
565          * returns the minimum space a manual label needs on the
566          * screen in pixels
567          */
568         int labelFill(Row const & row) const;
569
570         /// FIXME
571         int labelEnd(Row const & row) const;
572
573         ///
574         mutable std::vector<lyx::pos_type> log2vis_list;
575         ///
576         mutable std::vector<lyx::pos_type> vis2log_list;
577         ///
578         mutable std::vector<lyx::pos_type> bidi_levels;
579         ///
580         mutable lyx::pos_type bidi_start;
581         ///
582         mutable lyx::pos_type bidi_end;
583
584         ///
585         void charInserted();
586 public:
587         //
588         // special owner functions
589         ///
590         ParagraphList & ownerParagraphs() const;
591
592         /// return true if this is owned by an inset.
593         bool isInInset() const;
594
595 private:
596         /** Cursor related data.
597           Later this variable has to be removed. There should be now internal
598           cursor in a text */
599         ///
600         ///TextCursor cursor_;
601 };
602
603 /// return the default height of a row in pixels, considering font zoom
604 extern int defaultRowHeight();
605
606 #endif // LYXTEXT_H