]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
Remove the BufferView* arg from almost all LyXText class functions.
[lyx.git] / src / lyxtext.h
1 // -*- C++ -*-
2 /* This file is part of
3  * ======================================================
4  *
5  *           LyX, The Document Processor
6  *
7  *           Copyright 1995 Matthias Ettrich
8  *           Copyright 1995-2001 The LyX Team.
9  *
10  * ====================================================== */
11
12 #ifndef LYXTEXT_H
13 #define LYXTEXT_H
14
15 #include "lyxfont.h"
16 #include "lyxcursor.h"
17 #include "layout.h"
18 #include "LColor.h"
19 #include "insets/inset.h"
20
21 class Buffer;
22 class BufferParams;
23 class BufferView;
24 class InsetText;
25 class Paragraph;
26 class Row;
27 class Spacing;
28 class UpdatableInset;
29 class VSpace;
30 class WordLangTuple;
31 class ParagraphList;
32
33
34 /**
35   This class holds the mapping between buffer paragraphs and screen rows.
36   */
37 class LyXText {
38 public:
39         /// what repainting is needed
40         enum text_status {
41                 /// no repaint is needed
42                 UNCHANGED = 0,
43                 /**
44                  * A paint has caused a change in some rows
45                  * and rebreaking is needed.
46                  */
47                 CHANGED_IN_DRAW = 1,
48                 /// the refresh_row needs repainting
49                 NEED_VERY_LITTLE_REFRESH = 2,
50                 /// everything from refresh_y downwards needs repainting
51                 NEED_MORE_REFRESH = 3
52         };
53
54         ///
55         enum word_location {
56                 // the word around the cursor, only if the cursor is
57                 //not at a boundary
58                 WHOLE_WORD_STRICT,
59                 // the word around the cursor
60                 WHOLE_WORD,
61                 /// the word begining from the cursor position
62                 PARTIAL_WORD,
63                 /// the word around the cursor or before the cursor
64                 PREVIOUS_WORD,
65                 /// the next word (not yet used)
66                 NEXT_WORD
67         };
68
69         /// Constructor
70         LyXText(BufferView *);
71         /// sets inset as owner
72         LyXText(BufferView *, InsetText *);
73
74         /// Destructor
75         ~LyXText();
76
77         void init(BufferView *, bool reinit = false);
78         ///
79         mutable int height;
80         ///
81         mutable unsigned int width;
82         /// the current font settings
83         mutable LyXFont current_font;
84         /// the current font
85         mutable LyXFont real_current_font;
86 private:
87         /** the first visible row on screen
88          *  declared mutable because removeRow is const
89          */
90         mutable Row * top_row_;
91         /** the pixel offset with respect to this row of top_y
92          *  declared mutable because removeRow is const
93          */
94         mutable int top_row_offset_;
95 public:
96         /// get the y coord. of the top of the screen (relative to doc start)
97         int top_y() const;
98         /// set it
99         void top_y(int newy);
100         ///
101         InsetText * inset_owner;
102         ///
103         UpdatableInset * the_locking_inset;
104
105         ///
106         int getRealCursorX() const;
107         ///
108         LyXFont const getFont(Buffer const *, Paragraph * par,
109                 lyx::pos_type pos) const;
110         ///
111         LyXFont const getLayoutFont(Buffer const *, Paragraph * par) const;
112         ///
113         LyXFont const getLabelFont(Buffer const *, Paragraph * par) const;
114         ///
115         void setCharFont(Buffer const *, Paragraph * par,
116                          lyx::pos_type pos, LyXFont const & font);
117         void setCharFont(Paragraph * par,
118                          lyx::pos_type pos, LyXFont const & font, bool toggleall);
119
120         /// return true if the row changed
121         void markChangeInDraw(Row * row, Row * next);
122         ///
123         void breakAgainOneRow(Row * row);
124         /// what you expect when pressing <enter> at cursor position
125         void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
126
127         /** set layout over selection and make a total rebreak of
128           those paragraphs
129           */
130         Paragraph * setLayout(LyXCursor & actual_cursor,
131                               LyXCursor & selection_start,
132                               LyXCursor & selection_end,
133                               string const & layout);
134         ///
135         void setLayout(string const & layout);
136
137         /** increment depth over selection and make a total rebreak of those
138           paragraphs
139           */
140         void incDepth();
141
142         /** decrement depth over selection and make a total rebreak of those
143           paragraphs */
144         void decDepth();
145
146         /// get the depth at current cursor position
147         int getDepth() const;
148
149         /** set font over selection and make a total rebreak of those
150           paragraphs.
151           toggleall defaults to false.
152           */
153         void setFont(LyXFont const &, bool toggleall = false);
154
155         /** deletes and inserts again all paragaphs between the cursor
156           and the specified par. The Cursor is needed to set the refreshing
157           parameters.
158           This function is needed after SetLayout and SetFont etc.
159           */
160         void redoParagraphs(LyXCursor const & cursor,
161                             Paragraph const * end_par) const;
162         ///
163         void redoParagraph() const;
164
165         ///
166         void toggleFree(LyXFont const &, bool toggleall = false);
167
168         ///
169         string getStringToIndex();
170
171         /** recalculates the heights of all previous rows of the
172             specified paragraph.  needed, if the last characters font
173             has changed.
174             */
175         void redoHeightOfParagraph();
176
177         /** insert a character, moves all the following breaks in the
178           same Paragraph one to the right and make a little rebreak
179           */
180         void insertChar(char c);
181         ///
182         void insertInset(Inset * inset);
183
184         /// Completes the insertion with a full rebreak
185         void fullRebreak();
186
187         ///
188         mutable Row * need_break_row;
189
190         /// clear any pending paints
191         void clearPaint();
192
193         /// post notice that we changed during a draw
194         void postChangedInDraw();
195
196         /**
197          * Mark position y as the starting point for a repaint
198          */
199         void postPaint(int start_y);
200
201         /**
202          * Mark the given row at position y as needing a repaint.
203          */
204         void postRowPaint(Row * row, int start_y);
205
206         ///
207         Inset::RESULT dispatch(FuncRequest const & cmd);
208
209         BufferView * bv();
210
211         BufferView * bv() const;
212
213         friend class LyXScreen;
214
215         /**
216          * Return the status. This represents what repaints are
217          * pending after some operation (e.g. inserting a char).
218          */
219         text_status status() const;
220
221 private:
222         /**
223          * The pixel y position from which to repaint the screen.
224          * The position is absolute along the height of outermost
225          * lyxtext (I think). NEED_MORE_REFRESH and NEED_LITTLE_REFRESH
226          * repaints both use this as a starting point (if it's within
227          * the viewable portion of the lyxtext).
228          */
229         int refresh_y;
230         /**
231          * The row from which to repaint the screen, used by screen.c.
232          * This must be set if the pending update is NEED_LITTLE_REFRESH.
233          * It doesn't make any difference for NEED_MORE_REFRESH.
234          */
235         mutable Row * refresh_row;
236
237         /// refresh status
238         text_status status_;
239
240         /// only the top-level LyXText has this non-zero
241         BufferView * bv_owner;
242
243 public:
244         /** returns a pointer to the row near the specified y-coordinate
245           (relative to the whole text). y is set to the real beginning
246           of this row
247           */
248         Row * getRowNearY(int & y) const;
249
250         /** returns the column near the specified x-coordinate of the row
251          x is set to the real beginning of this column
252          */
253         lyx::pos_type getColumnNearX(Row * row,
254                                             int & x, bool & boundary) const;
255
256         /** returns a pointer to a specified row. y is set to the beginning
257          of the row
258          */
259         Row * getRow(Paragraph * par, lyx::pos_type pos, int & y) const;
260         /** returns the firstrow, this could be done with the above too but
261             IMO it's stupid to have to allocate a dummy y all the time I need
262             the first row
263         */
264         Row * firstRow() { return firstrow; }
265
266         /** The cursor.
267           Later this variable has to be removed. There should be now internal
268           cursor in a text (and thus not in a buffer). By keeping this it is
269           (I think) impossible to have several views with the same buffer, but
270           the cursor placed at different places.
271           [later]
272           Since the LyXText now has been moved from Buffer to BufferView
273           it should not be absolutely needed to move the cursor...
274           */
275         mutable LyXCursor cursor; // actual cursor position
276
277         /** The structure that keeps track of the selections set. */
278         struct Selection {
279                 Selection()
280                         : set_(false), mark_(false)
281                         {}
282                 bool set() const {
283                         return set_;
284                 }
285                 void set(bool s) {
286                         set_ = s;
287                 }
288                 bool mark() const {
289                         return mark_;
290                 }
291                 void mark(bool m) {
292                         mark_ = m;
293                 }
294                 LyXCursor cursor; // temporary cursor to hold a cursor position
295                                   // until setSelection is called!
296                 LyXCursor start;  // start of a REAL selection
297                 LyXCursor end;    // end of a REAL selection
298         private:
299                 bool set_; // former selection
300                 bool mark_; // former mark_set
301
302         };
303         mutable Selection selection;
304         // this is used to handle XSelection events in the right manner
305         mutable Selection xsel_cache;
306
307         /// needed for the toggling (cursor position on last selection made)
308         mutable LyXCursor last_sel_cursor;
309         /// needed for toggling the selection in screen.C
310         mutable LyXCursor toggle_cursor;
311         /// needed for toggling the selection in screen.C
312         mutable LyXCursor toggle_end_cursor;
313
314         /// need the selection cursor:
315         void setSelection();
316         ///
317         void clearSelection() const;
318         ///
319         string const selectionAsString(Buffer const *, bool label) const;
320
321         /// select the word we need depending on word_location
322         void getWord(LyXCursor & from, LyXCursor & to,
323                      word_location const) const;
324         /// just selects the word the cursor is in
325         void selectWord(word_location const);
326         /// returns the inset at cursor (if it exists), 0 otherwise
327         Inset * getInset() const;
328
329         /// accept selected change
330         void acceptChange();
331
332         /// reject selected change
333         void rejectChange();
334
335         /** 'selects" the next word, where the cursor is not in
336          and returns this word as string. THe cursor will be moved
337          to the beginning of this word.
338          With SelectSelectedWord can this be highlighted really
339          */
340         WordLangTuple const selectNextWordToSpellcheck(float & value) const;
341         ///
342         void selectSelectedWord();
343         /// returns true if par was empty and was removed
344         bool setCursor(Paragraph * par,
345                        lyx::pos_type pos,
346                        bool setfont = true,
347                        bool boundary = false) const;
348         ///
349         void setCursor(LyXCursor &, Paragraph * par,
350                        lyx::pos_type pos,
351                        bool boundary = false) const;
352         ///
353         void setCursorIntern(Paragraph * par,
354                              lyx::pos_type pos,
355                              bool setfont = true,
356                              bool boundary = false) const;
357         ///
358         void setCurrentFont() const;
359
360         ///
361         bool isBoundary(Buffer const *, Paragraph * par,
362                         lyx::pos_type pos) const;
363         ///
364         bool isBoundary(Buffer const *, Paragraph * par,
365                          lyx::pos_type pos,
366                          LyXFont const & font) const;
367
368         ///
369         void setCursorFromCoordinates(int x, int y) const;
370         ///
371         void setCursorFromCoordinates(LyXCursor &,
372                                       int x, int y) const;
373         ///
374         void cursorUp(bool selecting = false) const;
375         ///
376         void cursorDown(bool selecting = false) const;
377         ///
378         void cursorLeft(bool internal = true) const;
379         ///
380         void cursorRight(bool internal = true) const;
381         ///
382         void cursorLeftOneWord() const;
383         ///
384         void cursorRightOneWord() const;
385         ///
386         void cursorUpParagraph() const;
387         ///
388         void cursorDownParagraph() const;
389         ///
390         void cursorHome() const;
391         ///
392         void cursorEnd() const;
393         ///
394         void cursorPrevious();
395         ///
396         void cursorNext();
397         ///
398         void cursorTab() const;
399         ///
400         void cursorTop() const;
401         ///
402         void cursorBottom() const;
403         ///
404         void Delete();
405         ///
406         void backspace();
407         ///
408         bool selectWordWhenUnderCursor(word_location);
409         ///
410         enum TextCase {
411                 ///
412                 text_lowercase = 0,
413                 ///
414                 text_capitalization = 1,
415                 ///
416                 text_uppercase = 2
417         };
418         /// Change the case of the word at cursor position.
419         void changeCase(TextCase action);
420         ///
421         void transposeChars();
422
423         ///
424         void toggleInset();
425         ///
426         void cutSelection(bool doclear = true, bool realcut = true);
427         ///
428         void copySelection();
429         ///
430         void pasteSelection();
431         ///
432         void copyEnvironmentType();
433         ///
434         void pasteEnvironmentType();
435
436         /** the DTP switches for paragraphs. LyX will store the top settings
437          always in the first physical paragraph, the bottom settings in the
438          last. When a paragraph is broken, the top settings rest, the bottom
439          settings are given to the new one. So I can make shure, they do not
440          duplicate themself (and you cannnot make dirty things with them! )
441          */
442         void setParagraph(bool line_top, bool line_bottom,
443                           bool pagebreak_top, bool pagebreak_bottom,
444                           VSpace const & space_top,
445                           VSpace const & space_bottom,
446                           Spacing const & spacing,
447                           LyXAlignment align,
448                           string const & labelwidthstring,
449                           bool noindent);
450
451         /* these things are for search and replace */
452
453         /**
454          * Sets the selection from the current cursor position to length
455          * characters to the right. No safety checks.
456          */
457         void setSelectionRange(lyx::pos_type length);
458
459         /** simple replacing. The font of the first selected character
460           is used
461           */
462         void replaceSelectionWithString(string const & str);
463
464         /// needed to insert the selection
465         void insertStringAsLines(string const & str);
466         /// needed to insert the selection
467         void insertStringAsParagraphs(string const & str);
468
469         /// Find next inset of some specified type.
470         bool gotoNextInset(std::vector<Inset::Code> const & codes,
471                            string const & contents = string()) const;
472         ///
473         void gotoInset(std::vector<Inset::Code> const & codes,
474                        bool same_content);
475         ///
476         void gotoInset(Inset::Code code, bool same_content);
477         ///
478
479         /* for the greater insets */
480
481         /// returns false if inset wasn't found
482         bool updateInset(Inset *);
483         ///
484         void checkParagraph(Paragraph * par, lyx::pos_type pos);
485         ///
486         int workWidth() const;
487         ///
488         int workWidth(Inset * inset) const;
489         ///
490         void computeBidiTables(Buffer const *, Row * row) const;
491
492         /// Maps positions in the visual string to positions in logical string.
493         inline
494         lyx::pos_type log2vis(lyx::pos_type pos) const {
495                 if (bidi_start == -1)
496                         return pos;
497                 else
498                         return log2vis_list[pos-bidi_start];
499         }
500
501         /// Maps positions in the logical string to positions in visual string.
502         inline
503         lyx::pos_type vis2log(lyx::pos_type pos) const {
504                 if (bidi_start == -1)
505                         return pos;
506                 else
507                         return vis2log_list[pos-bidi_start];
508         }
509         ///
510         inline
511         lyx::pos_type bidi_level(lyx::pos_type pos) const {
512                 if (bidi_start == -1)
513                         return 0;
514                 else
515                         return bidi_levels[pos-bidi_start];
516         }
517         ///
518         inline
519         bool bidi_InRange(lyx::pos_type pos) const {
520                 return bidi_start == -1 ||
521                         (bidi_start <= pos && pos <= bidi_end);
522         }
523 private:
524         ///
525         mutable Row * firstrow;
526         ///
527         mutable Row * lastrow;
528
529         ///
530         void cursorLeftOneWord(LyXCursor &) const;
531
532         ///
533         float getCursorX(Row *, lyx::pos_type pos,
534                          lyx::pos_type last, bool boundary) const;
535         /// used in setlayout
536         void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
537
538         /** forces the redrawing of a paragraph. Needed when manipulating a
539             right address box
540             */
541         void redoDrawingOfParagraph(LyXCursor const & cursor);
542
543         /** Copybuffer for copy environment type.
544           Asger has learned that this should be a buffer-property instead
545           Lgb has learned that 'char' is a lousy type for non-characters
546           */
547         string copylayouttype;
548
549         /** inserts a new row behind the specified row, increments
550             the touched counters */
551         void insertRow(Row * row, Paragraph * par, lyx::pos_type pos) const;
552         /// removes the row and reset the touched counters
553         void removeRow(Row * row) const;
554
555         /// remove all following rows of the paragraph of the specified row.
556         void removeParagraph(Row * row) const;
557
558         /// insert the specified paragraph behind the specified row
559         void insertParagraph(Paragraph * par, Row * row) const;
560
561         /** appends  the implizit specified paragraph behind the specified row,
562          * start at the implizit given position */
563         void appendParagraph(Row * row) const;
564
565         ///
566         void breakAgain(Row * row) const;
567         /// Calculate and set the height of the row
568         void setHeightOfRow(Row * row_ptr) const;
569
570         // fix the cursor `cur' after a characters has been deleted at `where'
571         // position. Called by deleteEmptyParagraphMechanism
572         void fixCursorAfterDelete(LyXCursor & cur,
573                                   LyXCursor const & where) const;
574
575         /// delete double space (false) or empty paragraphs (true) around old_cursor
576         bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor) const;
577
578 public:
579         /** Updates all counters starting BEHIND the row. Changed paragraphs
580          * with a dynamic left margin will be rebroken. */
581         void updateCounters() const;
582         ///
583         void update(bool changed = true);
584         /**
585          * Returns an inset if inset was hit, or 0 if not.
586          * If hit, the coordinates are changed relative to the inset.
587          */
588         Inset * checkInsetHit(int & x, int & y) const;
589
590         ///
591         int singleWidth(Paragraph * par,
592                 lyx::pos_type pos) const;
593         ///
594         int singleWidth(Paragraph * par,
595                 lyx::pos_type pos, char c) const;
596
597         /// return the color of the canvas
598         LColor::color backgroundColor() const;
599
600         ///
601         mutable bool bidi_same_direction;
602
603         unsigned char transformChar(unsigned char c, Paragraph * par,
604                                     lyx::pos_type pos) const;
605
606         /**
607          * Returns the left beginning of the text.
608          * This information cannot be taken from the layout object, because
609          * in LaTeX the beginning of the text fits in some cases
610          * (for example sections) exactly the label-width.
611          */
612         int leftMargin(Row const * row) const;
613         ///
614         int rightMargin(Buffer const &, Row const & row) const;
615
616         /** this calculates the specified parameters. needed when setting
617          * the cursor and when creating a visible row */
618         void prepareToPrint(Row * row, float & x,
619                             float & fill_separator,
620                             float & fill_hfill,
621                             float & fill_label_hfill,
622                             bool bidi = true) const;
623
624 private:
625         ///
626         void setCounter(Buffer const *, Paragraph * par) const;
627         ///
628         void deleteWordForward();
629         ///
630         void deleteWordBackward();
631         ///
632         void deleteLineForward();
633
634         /*
635          * some low level functions
636          */
637
638
639         /// return the pos value *before* which a row should break.
640         /// for example, the pos at which IsNewLine(pos) == true
641         lyx::pos_type rowBreakPoint(Row const & row) const;
642
643         /// returns the minimum space a row needs on the screen in pixel
644         int fill(Row & row, int workwidth) const;
645
646         /**
647          * returns the minimum space a manual label needs on the
648          * screen in pixels
649          */
650         int labelFill(Row const & row) const;
651
652         /// FIXME
653         int labelEnd(Row const & row) const;
654
655         ///
656         mutable std::vector<lyx::pos_type> log2vis_list;
657
658         ///
659         mutable std::vector<lyx::pos_type> vis2log_list;
660
661         ///
662         mutable std::vector<lyx::pos_type> bidi_levels;
663
664         ///
665         mutable lyx::pos_type bidi_start;
666
667         ///
668         mutable lyx::pos_type bidi_end;
669
670         ///
671         void charInserted();
672 public:
673         //
674         // special owner functions
675         ///
676         Paragraph * ownerParagraph() const;
677         //
678         void ownerParagraph(Paragraph *) const;
679         // set it searching first for the right owner using the paragraph id
680         void ownerParagraph(int id, Paragraph *) const;
681
682         /// return true if this is owned by an inset.
683         bool isInInset() const;
684 };
685
686 /// return the default height of a row in pixels, considering font zoom
687 extern int defaultRowHeight();
688
689 #endif // LYXTEXT_H