]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
413ec2a6e19631af00613acdfe5cee228ede5e2f
[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 #ifdef __GNUG__
16 #pragma interface
17 #endif
18
19 #include "lyxfont.h"
20 #include "undo.h"
21 #include "lyxcursor.h"
22 #include "lyxparagraph.h"
23 #include "layout.h"
24 #include "lyxrow.h"
25
26 class Buffer;
27 class BufferParams;
28 class BufferView;
29 class InsetText;
30
31
32 /**
33   This class holds the mapping between buffer paragraphs and screen rows.
34   */
35 class LyXText {
36 public:
37         ///
38         enum text_status {
39                 ///
40                 UNCHANGED,
41                 ///
42                 NEED_MORE_REFRESH,
43                 ///
44                 NEED_VERY_LITTLE_REFRESH,
45                 ///
46                 CHANGED_IN_DRAW
47         };
48
49         /// Constructor
50         LyXText(BufferView *);
51         ///
52         LyXText(InsetText *);
53    
54         /// Destructor
55         ~LyXText();
56
57         void init(BufferView *);
58         ///
59         mutable int number_of_rows;
60         ///
61         mutable int height;
62         ///
63         mutable unsigned int width;
64         /// the current font settings
65         mutable LyXFont current_font;
66         /// the current font
67         mutable LyXFont real_current_font;
68         /// first visible pixel-row is set from LyXScreen!!!
69         // unsigned is wrong here for text-insets!
70         int first;
71         ///
72         BufferView * bv_owner;
73         ///
74         InsetText * inset_owner;
75         ///
76         UpdatableInset * the_locking_inset;
77
78         ///
79         int GetRealCursorX(BufferView *) const;
80         ///
81         LyXFont const GetFont(Buffer const *, LyXParagraph * par,
82                         LyXParagraph::size_type pos) const;
83         ///
84         void SetCharFont(Buffer const *, LyXParagraph * par,
85                          LyXParagraph::size_type pos, LyXFont const & font);
86         void SetCharFont(BufferView *, LyXParagraph * par,
87                          LyXParagraph::size_type pos,
88                          LyXFont const & font, bool toggleall);
89         /// returns a pointer to the very first LyXParagraph
90         LyXParagraph * FirstParagraph() const;
91   
92         /// what you expect when pressing <enter> at cursor position
93         void BreakParagraph(BufferView *, char keep_layout = 0);
94
95         /** set layout over selection and make a total rebreak of
96           those paragraphs
97           */
98         LyXParagraph * SetLayout(BufferView *, LyXCursor & actual_cursor,
99                                  LyXCursor & selection_start,
100                                  LyXCursor & selection_end,
101                                  LyXTextClass::size_type layout);
102         void SetLayout(BufferView *, LyXTextClass::size_type layout);
103         
104         /// used in setlayout
105         void MakeFontEntriesLayoutSpecific(Buffer const *, LyXParagraph * par);
106         
107         /** increment depth over selection and make a total rebreak of those 
108           paragraphs
109           */
110         void IncDepth(BufferView *);
111         
112         /** decrement depth over selection and make a total rebreak of those  
113           paragraphs */
114         void DecDepth(BufferView *);
115
116         /** Get the depth at current cursor position
117          */
118         int GetDepth() const { return cursor.par()->GetDepth(); }
119         
120         /** set font over selection and make a total rebreak of those
121           paragraphs.
122           toggleall defaults to false.
123           */
124         void SetFont(BufferView *, LyXFont const &, bool toggleall = false);
125         
126         /** deletes and inserts again all paragaphs between the cursor
127           and the specified par. The Cursor is needed to set the refreshing
128           parameters. 
129           This function is needed after SetLayout and SetFont etc.
130           */
131         void RedoParagraphs(BufferView *, LyXCursor const & cursor,
132                             LyXParagraph const * end_par) const;
133         ///
134         void RedoParagraph(BufferView *) const;
135         
136         ///
137         void ToggleFree(BufferView *, LyXFont const &, bool toggleall = false);
138         
139         /** recalculates the heights of all previous rows of the
140             specified paragraph.  needed, if the last characters font
141             has changed.  
142             */
143         void RedoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
144         
145         /** forces the redrawing of a paragraph. Needed when manipulating a 
146             right address box
147             */ 
148         void RedoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
149         
150         /** insert a character, moves all the following breaks in the 
151           same Paragraph one to the right and make a little rebreak
152           */
153         void InsertChar(BufferView *, char c);
154         ///
155         void InsertInset(BufferView *, Inset * inset);
156    
157         /** Completes the insertion with a full rebreak.
158             Returns true if something was broken. */
159         bool FullRebreak(BufferView *);
160
161         ///
162         Row * need_break_row;
163         ///
164         mutable int refresh_y;
165         ///
166         int refresh_height;
167         ///
168         int refresh_width;
169         ///
170         int refresh_x;
171         ///
172         mutable Row * refresh_row;
173         ///
174         int refresh_pos;
175         
176         /** wether the screen needs a refresh,
177            starting with refresh_y
178            */
179         mutable text_status status;
180         
181         /** returns a pointer to the row near the specified y-coordinate
182           (relative to the whole text). y is set to the real beginning
183           of this row
184           */ 
185         Row * GetRowNearY(int & y) const;
186         
187         /** returns the column near the specified x-coordinate of the row 
188          x is set to the real beginning of this column
189          */ 
190         int GetColumnNearX(BufferView *, Row * row,
191                            int & x, bool & boundary) const;
192         
193         /** returns a pointer to a specified row. y is set to the beginning
194          of the row
195          */
196         Row * GetRow(LyXParagraph * par,
197                      LyXParagraph::size_type pos, int & y) const;
198
199         /** returns the height of a default row, needed  for scrollbar
200          */
201         int DefaultHeight() const;
202    
203         /** The cursor.
204           Later this variable has to be removed. There should be now internal
205           cursor in a text (and thus not in a buffer). By keeping this it is
206           (I think) impossible to have several views with the same buffer, but
207           the cursor placed at different places.
208           [later]
209           Since the LyXText now has been moved from Buffer to BufferView
210           it should not be absolutely needed to move the cursor...
211           */
212         mutable LyXCursor cursor;
213
214 #if 0
215         /* the selection cursor */
216         /// 
217         mutable bool selection;
218         ///
219         mutable bool mark_set;
220
221         ///
222         mutable LyXCursor sel_cursor;
223         ///
224         mutable LyXCursor sel_start_cursor;
225         ///
226         mutable LyXCursor sel_end_cursor;
227 #else
228         /** The structrue that keeps track of the selections set. */
229         struct Selection {
230                 bool set() const {
231                         return set_;
232                 }
233                 void set(bool s) {
234                         set_ = s;
235                 }
236                 bool mark() const {
237                         return mark_;
238                 }
239                 void mark(bool m) {
240                         mark_ = m;
241                 }
242                 LyXCursor cursor;
243                 LyXCursor start;
244                 LyXCursor end;
245         private:
246                 bool set_; // former selection
247                 bool mark_; // former mark_set
248                 
249         };
250         mutable Selection selection;
251 #endif
252         /// needed for the toggling
253         LyXCursor last_sel_cursor;
254         ///
255         LyXCursor toggle_cursor;
256         ///
257         LyXCursor toggle_end_cursor;
258    
259         /// need the selection cursor:
260         void SetSelection(BufferView *);
261         ///
262         void ClearSelection(BufferView *) const;
263         ///
264         string const selectionAsString(Buffer const *) const;
265         
266         /// just selects the word the cursor is in
267         void SelectWord(BufferView *);
268
269         /** 'selects" the next word, where the cursor is not in 
270          and returns this word as string. THe cursor will be moved 
271          to the beginning of this word. 
272          With SelectSelectedWord can this be highlighted really
273          */ 
274         string const SelectNextWord(BufferView *, float & value) const;
275         ///
276         void SelectSelectedWord(BufferView *);
277         ///
278         void SetCursor(BufferView *, LyXParagraph * par,
279                        LyXParagraph::size_type pos,
280                        bool setfont = true,
281                        bool boundary = false) const;
282         ///
283         void SetCursor(BufferView *, LyXCursor &, LyXParagraph * par,
284                        LyXParagraph::size_type pos,
285                        bool boundary = false) const;
286         ///
287         void SetCursorIntern(BufferView *, LyXParagraph * par,
288                              LyXParagraph::size_type pos,
289                              bool setfont = true,
290                              bool boundary = false) const;
291         ///
292         void SetCurrentFont(BufferView *) const;
293
294         ///
295         bool IsBoundary(Buffer const *, LyXParagraph * par,
296                         LyXParagraph::size_type pos) const;
297         ///
298         bool IsBoundary(Buffer const *, LyXParagraph * par,
299                          LyXParagraph::size_type pos,
300                          LyXFont const & font) const;
301
302         ///
303         void SetCursorFromCoordinates(BufferView *, int x, int y) const;
304         ///
305         void SetCursorFromCoordinates(BufferView *, LyXCursor &,
306                                       int x, int y) const;
307         ///
308         void CursorUp(BufferView *) const;
309         ///
310         void CursorDown(BufferView *) const;
311         ///
312         void CursorLeft(BufferView *, bool internal = true) const;
313         ///
314         void CursorRight(BufferView *, bool internal = true) const;
315         ///
316         void CursorLeftOneWord(BufferView *) const;
317         ///
318         void CursorRightOneWord(BufferView *) const;
319         ///
320         void CursorUpParagraph(BufferView *) const;
321         ///
322         void CursorDownParagraph(BufferView *) const;
323         ///
324         void CursorHome(BufferView *) const;
325         ///
326         void CursorEnd(BufferView *) const;
327         ///
328         void CursorTab(BufferView *) const;
329         ///
330         void CursorTop(BufferView *) const;
331         ///
332         void CursorBottom(BufferView *) const;
333         ///
334         void Delete(BufferView *);
335         ///
336         void Backspace(BufferView *);
337         ///
338         void DeleteWordForward(BufferView *);
339         ///
340         void DeleteWordBackward(BufferView *);
341         ///
342         void DeleteLineForward(BufferView *);
343         ///
344         bool SelectWordWhenUnderCursor(BufferView *);
345         ///
346         enum TextCase {
347                 ///
348                 text_lowercase = 0,
349                 ///
350                 text_capitalization = 1,
351                 ///
352                 text_uppercase = 2
353         };
354         /// Change the case of the word at cursor position.
355         void ChangeWordCase(BufferView *, TextCase action);
356         void TransposeChars(BufferView const &);
357         
358         /** returns a printed row in a pixmap. The y value is needed to
359           decide, wether it is selected text or not. This is a strange
360           solution but faster.
361          */
362         void GetVisibleRow(BufferView *, int y_offset, int x_offset,
363                            Row * row_ptr, int y, bool cleared=false);
364
365         ///
366         void CutSelection(BufferView *, bool = true);
367         ///
368         void CopySelection(BufferView *);
369         ///
370         void PasteSelection(BufferView *);
371         ///
372         void copyEnvironmentType();
373         ///
374         void pasteEnvironmentType(BufferView *);
375         ///
376         void InsertFootnote();
377         ///
378         void InsertMarginpar();
379         ///
380         void InsertFigure();
381         ///
382         void InsertTabular();
383
384         /** the DTP switches for paragraphs. LyX will store the top settings
385          always in the first physical paragraph, the bottom settings in the
386          last. When a paragraph is broken, the top settings rest, the bottom 
387          settings are given to the new one. So I can make shure, they do not
388          duplicate themself (and you cannnot make dirty things with them! )
389          */ 
390         void SetParagraph(BufferView *,
391                           bool line_top, bool line_bottom,
392                           bool pagebreak_top, bool pagebreak_bottom,
393                           VSpace const & space_top,
394                           VSpace const & space_bottom,
395                           LyXAlignment align, 
396                           string labelwidthstring,
397                           bool noindent);
398
399         /* these things are for search and replace */
400
401         /** sets the selection over the number of characters of string,
402           no check!!
403           */
404         void SetSelectionOverString(BufferView *, string const & str);
405
406         /** simple replacing. The font of the first selected character
407           is used
408           */
409         void ReplaceSelectionWithString(BufferView *, string const & str);
410
411         /// needed to insert the selection
412         void InsertStringA(BufferView *, string const & str);
413         /// needed to insert the selection
414         void InsertStringB(BufferView *, string const & str);
415
416         /// Find next inset of some specified type.
417         bool GotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
418                            string const & contents = string()) const;
419         ///
420
421         /* for the greater insets */
422   
423         /// returns false if inset wasn't found
424         bool UpdateInset(BufferView *, Inset *);
425         ///
426         void CheckParagraph(BufferView *, LyXParagraph * par,
427                             LyXParagraph::size_type pos);
428         ///
429         int NumberOfCell(LyXParagraph * par,
430                          LyXParagraph::size_type pos) const;
431         ///
432         LyXParagraph * GetParFromID(int id);
433
434         // undo functions
435         /// returns false if no undo possible
436         bool TextUndo(BufferView *);
437         /// returns false if no redo possible
438         bool TextRedo(BufferView *);
439         /// used by TextUndo/TextRedo
440         bool TextHandleUndo(BufferView *, Undo * undo);
441         /// makes sure the next operation will be stored
442         void FinishUndo();
443         /// this is dangerous and for internal use only
444         void FreezeUndo();
445         /// this is dangerous and for internal use only
446         void UnFreezeUndo();
447         /// the flag used by FinishUndo();
448         mutable bool undo_finished;
449         /// a flag
450         bool undo_frozen;
451         ///
452         void SetUndo(Buffer *, Undo::undo_kind kind,
453                      LyXParagraph const * before,
454                      LyXParagraph const * end) const;
455         ///
456         void SetRedo(Buffer *, Undo::undo_kind kind,
457                      LyXParagraph const * before,
458                      LyXParagraph const * end);
459         ///
460         Undo * CreateUndo(Buffer *, Undo::undo_kind kind,
461                           LyXParagraph const * before,
462                           LyXParagraph const * end) const;
463         /// for external use in lyx_cb.C
464         void SetCursorParUndo(Buffer *);
465         ///
466         void RemoveTableRow(LyXCursor & cursor) const;
467         ///
468         bool IsEmptyTableCell() const;
469         ///
470         void toggleAppendix(BufferView *);
471         ///
472         int workWidth(BufferView *) const;
473         ///
474         void ComputeBidiTables(Buffer const *, Row * row) const;
475
476         /// Maps positions in the visual string to positions in logical string.
477         inline
478         LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const {
479                 if (bidi_start == -1)
480                         return pos;
481                 else
482                         return log2vis_list[pos-bidi_start];
483         }
484
485         /// Maps positions in the logical string to positions in visual string.
486         inline
487         LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const {
488                 if (bidi_start == -1)
489                         return pos;
490                 else
491                         return vis2log_list[pos-bidi_start];
492         }
493         ///
494         inline
495         LyXParagraph::size_type bidi_level(LyXParagraph::size_type pos) const {
496                 if (bidi_start == -1)
497                         return 0;
498                 else
499                         return bidi_levels[pos-bidi_start];
500         }       
501         ///
502         inline
503         bool bidi_InRange(LyXParagraph::size_type pos) const {
504                 return bidi_start == -1 ||
505                         (bidi_start <= pos && pos <= bidi_end);
506         }
507 private:
508         ///
509         void init();
510         ///
511         mutable Row * firstrow;
512         ///
513         mutable Row * lastrow;
514
515         /** Copybuffer for copy environment type.
516           Asger has learned that this should be a buffer-property instead
517           Lgb has learned that 'char' is a lousy type for non-characters
518           */
519         LyXTextClass::size_type copylayouttype;
520
521         /** inserts a new row behind the specified row, increments
522             the touched counters */
523         void InsertRow(Row * row, LyXParagraph * par,
524                        LyXParagraph::size_type pos) const;
525         /** removes the row and reset the touched counters */
526         void RemoveRow(Row * row) const;
527
528         /** remove all following rows of the paragraph of the specified row. */
529         void RemoveParagraph(Row * row) const;
530
531         /** insert the specified paragraph behind the specified row */
532         void InsertParagraph(BufferView *,
533                              LyXParagraph * par, Row * row) const;
534
535         /** appends  the implizit specified paragraph behind the specified row,
536          * start at the implizit given position */
537         void AppendParagraph(BufferView *, Row * row) const;
538    
539         ///
540         void BreakAgain(BufferView *, Row * row) const;
541         ///
542         void BreakAgainOneRow(BufferView *, Row * row);
543         /// Calculate and set the height of the row
544         void SetHeightOfRow(BufferView *, Row * row_ptr) const;
545
546         /** this calculates the specified parameters. needed when setting
547          * the cursor and when creating a visible row */ 
548         void PrepareToPrint(BufferView *, Row * row, float & x,
549                             float & fill_separator, 
550                             float & fill_hfill,
551                             float & fill_label_hfill,
552                             bool bidi = true) const;
553
554         ///
555         void DeleteEmptyParagraphMechanism(BufferView *,
556                                            LyXCursor const & old_cursor) const;
557
558         /** Updates all counters starting BEHIND the row. Changed paragraphs
559          * with a dynamic left margin will be rebroken. */ 
560         void UpdateCounters(BufferView *, Row * row) const;
561         ///
562         void SetCounter(Buffer const *, LyXParagraph * par) const;
563    
564         /*
565          * some low level functions
566          */
567         
568         ///
569         int SingleWidth(BufferView *, LyXParagraph * par,
570                         LyXParagraph::size_type pos) const;
571         ///
572         int SingleWidth(BufferView *, LyXParagraph * par,
573                         LyXParagraph::size_type pos, char c) const;
574         ///
575         void draw(BufferView *, Row const * row,
576                   LyXParagraph::size_type & pos,
577                   int offset, float & x, bool cleared);
578
579         /// get the next breakpoint in a given paragraph
580         LyXParagraph::size_type NextBreakPoint(BufferView *, Row const * row,
581                                                int width) const;
582         /// returns the minimum space a row needs on the screen in pixel
583         int Fill(BufferView *, Row * row, int workwidth) const;
584         
585         /** returns the minimum space a manual label needs on the
586           screen in pixel */ 
587         int LabelFill(BufferView *, Row const * row) const;
588
589         ///
590         LyXParagraph::size_type
591         BeginningOfMainBody(Buffer const *, LyXParagraph const * par) const;
592         
593         /** Returns the left beginning of the text.
594           This information cannot be taken from the layouts-objekt, because
595           in LaTeX the beginning of the text fits in some cases
596           (for example sections) exactly the label-width.
597           */
598         int LeftMargin(BufferView *, Row const * row) const;
599         ///
600         int RightMargin(Buffer const *, Row const * row) const;
601         ///
602         int LabelEnd (BufferView *, Row const * row) const;
603
604         /** returns the number of separators in the specified row.
605           The separator on the very last column doesnt count
606           */ 
607         int NumberOfSeparators(Buffer const *, Row const * row) const;
608
609         /** returns the number of hfills in the specified row. The
610           LyX-Hfill is a LaTeX \hfill so that the hfills at the
611           beginning and at the end were ignored. This is {\em MUCH}
612           more usefull than not to ignore!
613           */
614         int NumberOfHfills(Buffer const *, Row const * row) const;
615    
616         /// like NumberOfHfills, but only those in the manual label!
617         int NumberOfLabelHfills(Buffer const *, Row const * row) const;
618         /** returns true, if a expansion is needed. Rules are given by 
619           LaTeX
620           */
621         bool HfillExpansion(Buffer const *, Row const * row_ptr,
622                             LyXParagraph::size_type pos) const;
623
624
625         ///
626         mutable std::vector<LyXParagraph::size_type> log2vis_list;
627
628         ///
629         mutable std::vector<LyXParagraph::size_type> vis2log_list;
630
631         ///
632         mutable std::vector<LyXParagraph::size_type> bidi_levels;
633
634         ///
635         mutable LyXParagraph::size_type bidi_start;
636
637         ///
638         mutable LyXParagraph::size_type bidi_end;
639
640         ///
641         mutable bool bidi_same_direction;
642
643         ///
644         unsigned char TransformChar(unsigned char c, LyXParagraph * par,
645                                 LyXParagraph::size_type pos) const;
646
647         /** returns the paragraph position of the last character in the 
648           specified row
649           */
650         LyXParagraph::size_type RowLast(Row const * row) const;
651         ///
652         LyXParagraph::size_type RowLastPrintable(Row const * row) const;
653
654         ///
655         void charInserted();
656         //
657         // special owner functions
658         ///
659         LyXParagraph * OwnerParagraph() const;
660         //
661         LyXParagraph * OwnerParagraph(LyXParagraph *) const;
662 };
663
664
665 /* returns a pointer to the row near the specified y-coordinate
666  * (relative to the whole text). y is set to the real beginning
667  * of this row */
668 inline
669 Row * LyXText::GetRowNearY(int & y) const
670 {
671         // If possible we should optimize this method. (Lgb)
672         Row * tmprow = firstrow;
673         int tmpy = 0;
674         
675         while (tmprow->next() && tmpy + tmprow->height() <= y) {
676                 tmpy += tmprow->height();
677                 tmprow = tmprow->next();
678         }
679         
680         y = tmpy;   // return the real y
681         return tmprow;
682 }
683 #endif