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