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