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