]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
ccf137b1e29088712a52d6e13d3677e8cf09c200
[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 class MetricsInfo;
38 class Dimension;
39
40
41 /**
42   This class used to hold the mapping between buffer paragraphs and
43         screen rows. Nowadays, the Paragraphs take care of their rows
44   themselves and this contains just most of the code for manipulating 
45   them and interaction with the Cursor. 
46   */
47
48 // The inheritance from TextCursor should go. It's just there to ease
49 // transition...
50 class LyXText : public TextCursor {
51 public:
52         /// Constructor
53         LyXText(BufferView *, InsetText *, bool ininset,
54                 ParagraphList & paragraphs);
55
56         void init(BufferView *);
57         ///
58         int height;
59         ///
60         unsigned int width;
61         /// the current font settings
62         LyXFont current_font;
63         /// the current font
64         LyXFont real_current_font;
65         /// our buffer's default layout font
66         LyXFont defaultfont_;
67 private:
68         /// offset of dran area to document start.
69         int anchor_y_;
70 public:
71         /// update all cached row positions
72         void updateRowPositions();
73         /// get the y coord. of the top of the screen (relative to doc start)
74         int top_y() const;
75         /// set the y coord. of the top of the screen (relative to doc start)
76         void top_y(int newy);
77         /// set the anchoring row. top_y will be computed relative to this
78         void anchor_row(RowList::iterator rit);
79         ///
80         InsetText * inset_owner;
81         ///
82         UpdatableInset * the_locking_inset;
83
84         ///
85         int getRealCursorX() const;
86         ///
87         LyXFont getFont(ParagraphList::iterator pit, lyx::pos_type pos) const;
88         ///
89         LyXFont getLayoutFont(ParagraphList::iterator pit) const;
90         ///
91         LyXFont getLabelFont(ParagraphList::iterator pit) const;
92         ///
93         void setCharFont(ParagraphList::iterator pit,
94                          lyx::pos_type pos, LyXFont const & font);
95         void setCharFont(ParagraphList::iterator pit,
96                          lyx::pos_type pos,
97                          LyXFont const & font, bool toggleall);
98
99         /// what you expect when pressing <enter> at cursor position
100         void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
101
102         /** set layout over selection and make a total rebreak of
103           those paragraphs
104           */
105         ParagraphList::iterator
106         setLayout(LyXCursor & actual_cursor,
107                   LyXCursor & selection_start,
108                   LyXCursor & selection_end,
109                   string const & layout);
110         ///
111         void setLayout(string const & layout);
112
113         /**
114          * Increase or decrease the nesting depth of the selected paragraph(s)
115          * if test_only, don't change any depths. Returns whether something
116          * (would have) changed
117          */
118         bool changeDepth(bv_funcs::DEPTH_CHANGE type, bool test_only);
119
120         /// get the depth at current cursor position
121         int getDepth() const;
122
123         /** set font over selection and make a total rebreak of those
124           paragraphs.
125           toggleall defaults to false.
126           */
127         void setFont(LyXFont const &, bool toggleall = false);
128
129         /// rebreaks all paragaphs between the given pars.
130         void redoParagraphs(ParagraphList::iterator begin,
131                             ParagraphList::iterator end);
132         /// rebreaks the given par
133         void redoParagraph(ParagraphList::iterator pit);
134         /// rebreaks the cursor par
135         void redoParagraph();
136
137         ///
138         void toggleFree(LyXFont const &, bool toggleall = false);
139
140         ///
141         string getStringToIndex();
142
143         /** insert a character, moves all the following breaks in the
144           same Paragraph one to the right and make a little rebreak
145           */
146         void insertChar(char c);
147         ///
148         void insertInset(InsetOld * inset);
149
150         /// a full rebreak of the whole text
151         void fullRebreak();
152         /// compute text metrics
153         void metrics(MetricsInfo & mi, Dimension & dim);
154
155         ///
156         InsetOld::RESULT dispatch(FuncRequest const & cmd);
157
158         BufferView * bv();
159
160         BufferView * bv() const;
161
162         friend class LyXScreen;
163
164 public:
165         /// only the top-level LyXText has this non-zero
166         BufferView * bv_owner;
167
168 private:
169         /// returns a pointer to a specified row.
170         RowList::iterator
171         getRow(ParagraphList::iterator pit, lyx::pos_type pos) const;
172 public:
173         /// returns a pointer cursor row
174         RowList::iterator getRow(LyXCursor const & cursor) const;
175         /// convenience
176         RowList::iterator cursorRow() const;
177         /**
178          * Return the next row, when cursor is at the end of the
179          * previous row, for insets that take a full row.
180          *
181          * FIXME: explain why we need this ? especially for y...
182          */
183         RowList::iterator cursorIRow() const;
184
185         /** returns a pointer to the row near the specified y-coordinate
186           (relative to the whole text). y is set to the real beginning
187           of this row
188           */
189         RowList::iterator getRowNearY(int & y,
190                 ParagraphList::iterator & pit) const;
191
192         /** returns the column near the specified x-coordinate of the row
193          x is set to the real beginning of this column
194          */
195         lyx::pos_type getColumnNearX(ParagraphList::iterator pit,
196                 RowList::iterator rit, int & x, bool & boundary) const;
197
198         /** returns a pointer to a specified row. y is set to the beginning
199          of the row
200          */
201         RowList::iterator
202         getRow(ParagraphList::iterator pit, lyx::pos_type pos, int & y) const;
203
204         /// need the selection cursor:
205         void setSelection();
206         ///
207         void clearSelection();
208
209         /// select the word we need depending on word_location
210         void getWord(LyXCursor & from, LyXCursor & to, lyx::word_location const);
211         /// just selects the word the cursor is in
212         void selectWord(lyx::word_location loc);
213         /// returns the inset at cursor (if it exists), 0 otherwise
214         InsetOld * getInset() const;
215
216         /// accept selected change
217         void acceptChange();
218
219         /// reject selected change
220         void rejectChange();
221
222         /** 'selects" the next word, where the cursor is not in
223          and returns this word as string. THe cursor will be moved
224          to the beginning of this word.
225          With SelectSelectedWord can this be highlighted really
226          */
227         WordLangTuple const selectNextWordToSpellcheck(float & value);
228         ///
229         void selectSelectedWord();
230         /// re-computes the cached coordinates in the cursor
231         void redoCursor();
232         /// returns true if par was empty and was removed
233         bool setCursor(ParagraphList::iterator pit,
234                        lyx::pos_type pos,
235                        bool setfont = true,
236                        bool boundary = false);
237         ///
238         void setCursor(LyXCursor &, ParagraphList::iterator pit,
239                        lyx::pos_type pos,
240                        bool boundary = false);
241         ///
242         void setCursorIntern(ParagraphList::iterator pit,
243                              lyx::pos_type pos,
244                              bool setfont = true,
245                              bool boundary = false);
246         ///
247         void setCurrentFont();
248
249         ///
250         bool isBoundary(Buffer const *, Paragraph const & par,
251                         lyx::pos_type pos) const;
252         ///
253         bool isBoundary(Buffer const *, Paragraph const & par,
254                          lyx::pos_type pos,
255                          LyXFont const & font) const;
256
257         ///
258         void setCursorFromCoordinates(int x, int y);
259         ///
260         void setCursorFromCoordinates(LyXCursor &,
261                                       int x, int y);
262         ///
263         void cursorUp(bool selecting = false);
264         ///
265         void cursorDown(bool selecting = false);
266         ///
267         void cursorLeft(bool internal = true);
268         ///
269         void cursorRight(bool internal = true);
270         ///
271         void cursorLeftOneWord();
272         ///
273         void cursorRightOneWord();
274         ///
275         void cursorUpParagraph();
276         ///
277         void cursorDownParagraph();
278         ///
279         void cursorHome();
280         ///
281         void cursorEnd();
282         ///
283         void cursorPrevious();
284         ///
285         void cursorNext();
286         ///
287         void cursorTop();
288         ///
289         void cursorBottom();
290         ///
291         void Delete();
292         ///
293         void backspace();
294         ///
295         bool selectWordWhenUnderCursor(lyx::word_location);
296         ///
297         enum TextCase {
298                 ///
299                 text_lowercase = 0,
300                 ///
301                 text_capitalization = 1,
302                 ///
303                 text_uppercase = 2
304         };
305         /// Change the case of the word at cursor position.
306         void changeCase(TextCase action);
307
308         ///
309         void toggleInset();
310         ///
311         void cutSelection(bool doclear = true, bool realcut = true);
312         ///
313         void copySelection();
314         ///
315         void pasteSelection(size_t sel_index = 0);
316
317         /** the DTP switches for paragraphs. LyX will store the top settings
318          always in the first physical paragraph, the bottom settings in the
319          last. When a paragraph is broken, the top settings rest, the bottom
320          settings are given to the new one. So I can make shure, they do not
321          duplicate themself (and you cannnot make dirty things with them! )
322          */
323         void setParagraph(bool line_top, bool line_bottom,
324                           bool pagebreak_top, bool pagebreak_bottom,
325                           VSpace const & space_top,
326                           VSpace const & space_bottom,
327                           Spacing const & spacing,
328                           LyXAlignment align,
329                           string const & labelwidthstring,
330                           bool noindent);
331
332         /* these things are for search and replace */
333
334         /**
335          * Sets the selection from the current cursor position to length
336          * characters to the right. No safety checks.
337          */
338         void setSelectionRange(lyx::pos_type length);
339
340         /** simple replacing. The font of the first selected character
341           is used
342           */
343         void replaceSelectionWithString(string const & str);
344
345         /// needed to insert the selection
346         void insertStringAsLines(string const & str);
347         /// needed to insert the selection
348         void insertStringAsParagraphs(string const & str);
349
350         /// Find next inset of some specified type.
351         bool gotoNextInset(std::vector<InsetOld::Code> const & codes,
352                            string const & contents = string());
353         ///
354         void gotoInset(std::vector<InsetOld::Code> const & codes,
355                        bool same_content);
356         ///
357         void gotoInset(InsetOld::Code code, bool same_content);
358
359         ///
360         int workWidth() const;
361
362         ///
363         void computeBidiTables(ParagraphList::iterator pit,
364                 Buffer const *, RowList::iterator row) const;
365         /// Maps positions in the visual string to positions in logical string.
366         lyx::pos_type log2vis(lyx::pos_type pos) const;
367         /// Maps positions in the logical string to positions in visual string.
368         lyx::pos_type vis2log(lyx::pos_type pos) const;
369         ///
370         lyx::pos_type bidi_level(lyx::pos_type pos) const;
371         ///
372         bool bidi_InRange(lyx::pos_type pos) const;
373 private:
374         ///
375         float getCursorX(ParagraphList::iterator pit,
376              RowList::iterator rit, lyx::pos_type pos,
377                          lyx::pos_type last, bool boundary) const;
378         /// used in setlayout
379         void makeFontEntriesLayoutSpecific(BufferParams const &, Paragraph & par);
380
381         /// Calculate and set the height of the row
382         void setHeightOfRow(ParagraphList::iterator, RowList::iterator rit);
383
384         // fix the cursor `cur' after a characters has been deleted at `where'
385         // position. Called by deleteEmptyParagraphMechanism
386         void fixCursorAfterDelete(LyXCursor & cur, LyXCursor const & where);
387
388         /// delete double space (false) or empty paragraphs (true) around old_cursor
389         bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor);
390
391 public:
392         /** Updates all counters starting BEHIND the row. Changed paragraphs
393          * with a dynamic left margin will be rebroken. */
394         void updateCounters();
395         /**
396          * Returns an inset if inset was hit, or 0 if not.
397          * If hit, the coordinates are changed relative to the inset.
398          */
399         InsetOld * checkInsetHit(int & x, int & y);
400
401         ///
402         int singleWidth(ParagraphList::iterator pit, lyx::pos_type pos) const;
403         ///
404         int singleWidth(ParagraphList::iterator pit,
405                 lyx::pos_type pos, char c, LyXFont const & Font) const;
406
407         /// return the color of the canvas
408         LColor::color backgroundColor() const;
409
410         ///
411         mutable bool bidi_same_direction;
412
413         unsigned char transformChar(unsigned char c, Paragraph const & par,
414                                     lyx::pos_type pos) const;
415
416         /**
417          * Returns the left beginning of the text.
418          * This information cannot be taken from the layout object, because
419          * in LaTeX the beginning of the text fits in some cases
420          * (for example sections) exactly the label-width.
421          */
422         int leftMargin(ParagraphList::iterator pit, Row const & row) const;
423         ///
424         int rightMargin(ParagraphList::iterator pit, Buffer const &, Row const & row) const;
425
426         /** this calculates the specified parameters. needed when setting
427          * the cursor and when creating a visible row */
428         void prepareToPrint(ParagraphList::iterator pit,
429                 RowList::iterator row) const;
430
431 private:
432         ///
433         void setCounter(Buffer const *, ParagraphList::iterator pit);
434         ///
435         void deleteWordForward();
436         ///
437         void deleteWordBackward();
438         ///
439         void deleteLineForward();
440
441         /*
442          * some low level functions
443          */
444
445
446         /// sets row.end to the pos value *after* which a row should break.
447         /// for example, the pos after which isNewLine(pos) == true
448         lyx::pos_type rowBreakPoint(ParagraphList::iterator pit,
449                 Row const & row) const;
450
451         /// returns the minimum space a row needs on the screen in pixel
452         int fill(ParagraphList::iterator pit,
453                 RowList::iterator row, int workwidth) const;
454
455         /**
456          * returns the minimum space a manual label needs on the
457          * screen in pixels
458          */
459         int labelFill(ParagraphList::iterator pit, Row const & row) const;
460
461         /// FIXME
462         int labelEnd(ParagraphList::iterator pit, Row const & row) const;
463
464         ///
465         mutable std::vector<lyx::pos_type> log2vis_list;
466         ///
467         mutable std::vector<lyx::pos_type> vis2log_list;
468         ///
469         mutable std::vector<lyx::pos_type> bidi_levels;
470         ///
471         mutable lyx::pos_type bidi_start;
472         ///
473         mutable lyx::pos_type bidi_end;
474
475         ///
476         const bool in_inset_;
477         ///
478         ParagraphList & paragraphs_;
479
480         ///
481         void charInserted();
482 public:
483         //
484         // special owner functions
485         ///
486         ParagraphList & ownerParagraphs() const;
487
488         /// return true if this is owned by an inset.
489         bool isInInset() const;
490
491         /// return first row of text
492         RowList::iterator firstRow() const;
493         /// return last row of text
494         RowList::iterator lastRow() const;
495         /// return row "behind" last row of text
496         RowList::iterator endRow() const;
497         /// return next row crossing paragraph boundaries
498         void nextRow(ParagraphList::iterator & pit,
499                 RowList::iterator & rit) const;
500         /// return previous row crossing paragraph boundaries
501         void previousRow(ParagraphList::iterator & pit,
502                 RowList::iterator & rit) const;
503
504         ///
505         bool noRows() const;
506
507 private:
508         /** Cursor related data.
509           Later this variable has to be removed. There should be now internal
510           cursor in a text */
511         ///
512         ///TextCursor cursor_;
513 };
514
515 /// return the default height of a row in pixels, considering font zoom
516 extern int defaultRowHeight();
517
518 #endif // LYXTEXT_H