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