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