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