]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
84d266ce2075738daa85dd013849045fbabf5ae3
[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         /* the selection cursor */
215         /// 
216         mutable bool selection;
217         ///
218         mutable bool mark_set;
219
220         ///
221         mutable LyXCursor sel_cursor;
222         ///
223         mutable LyXCursor sel_start_cursor;
224         ///
225         mutable LyXCursor sel_end_cursor;
226         /// needed for the toggling
227         LyXCursor last_sel_cursor;
228         ///
229         LyXCursor toggle_cursor;
230         ///
231         LyXCursor toggle_end_cursor;
232    
233         /// need the selection cursor:
234         void SetSelection(BufferView *);
235         ///
236         void ClearSelection(BufferView *) const;
237         ///
238         string const selectionAsString(Buffer const *) const;
239         
240         /// just selects the word the cursor is in
241         void SelectWord(BufferView *);
242
243         /** 'selects" the next word, where the cursor is not in 
244          and returns this word as string. THe cursor will be moved 
245          to the beginning of this word. 
246          With SelectSelectedWord can this be highlighted really
247          */ 
248         string const SelectNextWord(BufferView *, float & value) const;
249         ///
250         void SelectSelectedWord(BufferView *);
251         ///
252         void SetCursor(BufferView *, LyXParagraph * par,
253                        LyXParagraph::size_type pos,
254                        bool setfont = true,
255                        bool boundary = false) const;
256         ///
257         void SetCursor(BufferView *, LyXCursor &, LyXParagraph * par,
258                        LyXParagraph::size_type pos,
259                        bool boundary = false) const;
260         ///
261         void SetCursorIntern(BufferView *, LyXParagraph * par,
262                              LyXParagraph::size_type pos,
263                              bool setfont = true,
264                              bool boundary = false) const;
265         ///
266         void SetCurrentFont(BufferView *) const;
267
268         ///
269         bool IsBoundary(Buffer const *, LyXParagraph * par,
270                         LyXParagraph::size_type pos) const;
271         ///
272         bool IsBoundary(Buffer const *, LyXParagraph * par,
273                          LyXParagraph::size_type pos,
274                          LyXFont const & font) const;
275
276         ///
277         void SetCursorFromCoordinates(BufferView *, int x, int y) const;
278         ///
279         void SetCursorFromCoordinates(BufferView *, LyXCursor &,
280                                       int x, int y) const;
281         ///
282         void CursorUp(BufferView *) const;
283         ///
284         void CursorDown(BufferView *) const;
285         ///
286         void CursorLeft(BufferView *, bool internal = true) const;
287         ///
288         void CursorRight(BufferView *, bool internal = true) const;
289         ///
290         void CursorLeftOneWord(BufferView *) const;
291         ///
292         void CursorRightOneWord(BufferView *) const;
293         ///
294         void CursorUpParagraph(BufferView *) const;
295         ///
296         void CursorDownParagraph(BufferView *) const;
297         ///
298         void CursorHome(BufferView *) const;
299         ///
300         void CursorEnd(BufferView *) const;
301         ///
302         void CursorTab(BufferView *) const;
303         ///
304         void CursorTop(BufferView *) const;
305         ///
306         void CursorBottom(BufferView *) const;
307         ///
308         void Delete(BufferView *);
309         ///
310         void Backspace(BufferView *);
311         ///
312         void DeleteWordForward(BufferView *);
313         ///
314         void DeleteWordBackward(BufferView *);
315         ///
316         void DeleteLineForward(BufferView *);
317         ///
318         bool SelectWordWhenUnderCursor(BufferView *);
319         ///
320         enum TextCase {
321                 ///
322                 text_lowercase = 0,
323                 ///
324                 text_capitalization = 1,
325                 ///
326                 text_uppercase = 2
327         };
328         /// Change the case of the word at cursor position.
329         void ChangeWordCase(BufferView *, TextCase action);
330         void TransposeChars(BufferView const &);
331         
332         /** returns a printed row in a pixmap. The y value is needed to
333           decide, wether it is selected text or not. This is a strange
334           solution but faster.
335          */
336         void GetVisibleRow(BufferView *, int y_offset, int x_offset,
337                            Row * row_ptr, int y, bool cleared=false);
338
339         ///
340         void CutSelection(BufferView *, bool = true);
341         ///
342         void CopySelection(BufferView *);
343         ///
344         void PasteSelection(BufferView *);
345         ///
346         void copyEnvironmentType();
347         ///
348         void pasteEnvironmentType(BufferView *);
349         ///
350         void InsertFootnote();
351         ///
352         void InsertMarginpar();
353         ///
354         void InsertFigure();
355         ///
356         void InsertTabular();
357
358         /** the DTP switches for paragraphs. LyX will store the top settings
359          always in the first physical paragraph, the bottom settings in the
360          last. When a paragraph is broken, the top settings rest, the bottom 
361          settings are given to the new one. So I can make shure, they do not
362          duplicate themself (and you cannnot make dirty things with them! )
363          */ 
364         void SetParagraph(BufferView *,
365                           bool line_top, bool line_bottom,
366                           bool pagebreak_top, bool pagebreak_bottom,
367                           VSpace const & space_top,
368                           VSpace const & space_bottom,
369                           LyXAlignment align, 
370                           string labelwidthstring,
371                           bool noindent);
372
373         /* these things are for search and replace */
374
375         /** sets the selection over the number of characters of string,
376           no check!!
377           */
378         void SetSelectionOverString(BufferView *, string const & str);
379
380         /** simple replacing. The font of the first selected character
381           is used
382           */
383         void ReplaceSelectionWithString(BufferView *, string const & str);
384
385         /// needed to insert the selection
386         void InsertStringA(BufferView *, string const & str);
387         /// needed to insert the selection
388         void InsertStringB(BufferView *, string const & str);
389
390         /// Find next inset of some specified type.
391         bool GotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
392                            string const & contents = string()) const;
393         ///
394
395         /* for the greater insets */
396   
397         /// returns false if inset wasn't found
398         bool UpdateInset(BufferView *, Inset *);
399         ///
400         void CheckParagraph(BufferView *, LyXParagraph * par,
401                             LyXParagraph::size_type pos);
402         ///
403         int NumberOfCell(LyXParagraph * par,
404                          LyXParagraph::size_type pos) const;
405         ///
406         LyXParagraph * GetParFromID(int id);
407
408         // undo functions
409         /// returns false if no undo possible
410         bool TextUndo(BufferView *);
411         /// returns false if no redo possible
412         bool TextRedo(BufferView *);
413         /// used by TextUndo/TextRedo
414         bool TextHandleUndo(BufferView *, Undo * undo);
415         /// makes sure the next operation will be stored
416         void FinishUndo();
417         /// this is dangerous and for internal use only
418         void FreezeUndo();
419         /// this is dangerous and for internal use only
420         void UnFreezeUndo();
421         /// the flag used by FinishUndo();
422         mutable bool undo_finished;
423         /// a flag
424         bool undo_frozen;
425         ///
426         void SetUndo(Buffer *, Undo::undo_kind kind,
427                      LyXParagraph const * before,
428                      LyXParagraph const * end) const;
429         ///
430         void SetRedo(Buffer *, Undo::undo_kind kind,
431                      LyXParagraph const * before,
432                      LyXParagraph const * end);
433         ///
434         Undo * CreateUndo(Buffer *, Undo::undo_kind kind,
435                           LyXParagraph const * before,
436                           LyXParagraph const * end) const;
437         /// for external use in lyx_cb.C
438         void SetCursorParUndo(Buffer *);
439         ///
440         void RemoveTableRow(LyXCursor & cursor) const;
441         ///
442         bool IsEmptyTableCell() const;
443         ///
444         void toggleAppendix(BufferView *);
445         ///
446         int workWidth(BufferView *) const;
447         ///
448         void ComputeBidiTables(Buffer const *, Row * row) const;
449
450         /// Maps positions in the visual string to positions in logical string.
451         inline
452         LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const {
453                 if (bidi_start == -1)
454                         return pos;
455                 else
456                         return log2vis_list[pos-bidi_start];
457         }
458
459         /// Maps positions in the logical string to positions in visual string.
460         inline
461         LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const {
462                 if (bidi_start == -1)
463                         return pos;
464                 else
465                         return vis2log_list[pos-bidi_start];
466         }
467         ///
468         inline
469         LyXParagraph::size_type bidi_level(LyXParagraph::size_type pos) const {
470                 if (bidi_start == -1)
471                         return 0;
472                 else
473                         return bidi_levels[pos-bidi_start];
474         }       
475         ///
476         inline
477         bool bidi_InRange(LyXParagraph::size_type pos) const {
478                 return bidi_start == -1 ||
479                         (bidi_start <= pos && pos <= bidi_end);
480         }
481 private:
482         ///
483         void init();
484         ///
485         mutable Row * firstrow;
486         ///
487         mutable Row * lastrow;
488
489         /** Copybuffer for copy environment type.
490           Asger has learned that this should be a buffer-property instead
491           Lgb has learned that 'char' is a lousy type for non-characters
492           */
493         LyXTextClass::size_type copylayouttype;
494
495         /** inserts a new row behind the specified row, increments
496             the touched counters */
497         void InsertRow(Row * row, LyXParagraph * par,
498                        LyXParagraph::size_type pos) const;
499         /** removes the row and reset the touched counters */
500         void RemoveRow(Row * row) const;
501
502         /** remove all following rows of the paragraph of the specified row. */
503         void RemoveParagraph(Row * row) const;
504
505         /** insert the specified paragraph behind the specified row */
506         void InsertParagraph(BufferView *,
507                              LyXParagraph * par, Row * row) const;
508
509         /** appends  the implizit specified paragraph behind the specified row,
510          * start at the implizit given position */
511         void AppendParagraph(BufferView *, Row * row) const;
512    
513         ///
514         void BreakAgain(BufferView *, Row * row) const;
515         ///
516         void BreakAgainOneRow(BufferView *, Row * row);
517         /// Calculate and set the height of the row
518         void SetHeightOfRow(BufferView *, Row * row_ptr) const;
519
520         /** this calculates the specified parameters. needed when setting
521          * the cursor and when creating a visible row */ 
522         void PrepareToPrint(BufferView *, Row * row, float & x,
523                             float & fill_separator, 
524                             float & fill_hfill,
525                             float & fill_label_hfill,
526                             bool bidi = true) const;
527
528         ///
529         void DeleteEmptyParagraphMechanism(BufferView *,
530                                            LyXCursor const & old_cursor) const;
531
532         /** Updates all counters starting BEHIND the row. Changed paragraphs
533          * with a dynamic left margin will be rebroken. */ 
534         void UpdateCounters(BufferView *, Row * row) const;
535         ///
536         void SetCounter(Buffer const *, LyXParagraph * par) const;
537    
538         /*
539          * some low level functions
540          */
541         
542         ///
543         int SingleWidth(BufferView *, LyXParagraph * par,
544                         LyXParagraph::size_type pos) const;
545         ///
546         int SingleWidth(BufferView *, LyXParagraph * par,
547                         LyXParagraph::size_type pos, char c) const;
548         ///
549         void draw(BufferView *, Row const * row,
550                   LyXParagraph::size_type & pos,
551                   int offset, float & x, bool cleared);
552
553         /// get the next breakpoint in a given paragraph
554         LyXParagraph::size_type NextBreakPoint(BufferView *, Row const * row,
555                                                int width) const;
556         /// returns the minimum space a row needs on the screen in pixel
557         int Fill(BufferView *, Row * row, int workwidth) const;
558         
559         /** returns the minimum space a manual label needs on the
560           screen in pixel */ 
561         int LabelFill(BufferView *, Row const * row) const;
562
563         ///
564         LyXParagraph::size_type
565         BeginningOfMainBody(Buffer const *, LyXParagraph const * par) const;
566         
567         /** Returns the left beginning of the text.
568           This information cannot be taken from the layouts-objekt, because
569           in LaTeX the beginning of the text fits in some cases
570           (for example sections) exactly the label-width.
571           */
572         int LeftMargin(BufferView *, Row const * row) const;
573         ///
574         int RightMargin(Buffer const *, Row const * row) const;
575         ///
576         int LabelEnd (BufferView *, Row const * row) const;
577
578         /** returns the number of separators in the specified row.
579           The separator on the very last column doesnt count
580           */ 
581         int NumberOfSeparators(Buffer const *, Row const * row) const;
582
583         /** returns the number of hfills in the specified row. The
584           LyX-Hfill is a LaTeX \hfill so that the hfills at the
585           beginning and at the end were ignored. This is {\em MUCH}
586           more usefull than not to ignore!
587           */
588         int NumberOfHfills(Buffer const *, Row const * row) const;
589    
590         /// like NumberOfHfills, but only those in the manual label!
591         int NumberOfLabelHfills(Buffer const *, Row const * row) const;
592         /** returns true, if a expansion is needed. Rules are given by 
593           LaTeX
594           */
595         bool HfillExpansion(Buffer const *, Row const * row_ptr,
596                             LyXParagraph::size_type pos) const;
597
598
599         ///
600         mutable std::vector<LyXParagraph::size_type> log2vis_list;
601
602         ///
603         mutable std::vector<LyXParagraph::size_type> vis2log_list;
604
605         ///
606         mutable std::vector<LyXParagraph::size_type> bidi_levels;
607
608         ///
609         mutable LyXParagraph::size_type bidi_start;
610
611         ///
612         mutable LyXParagraph::size_type bidi_end;
613
614         ///
615         mutable bool bidi_same_direction;
616
617         ///
618         unsigned char TransformChar(unsigned char c, LyXParagraph * par,
619                                 LyXParagraph::size_type pos) const;
620
621         /** returns the paragraph position of the last character in the 
622           specified row
623           */
624         LyXParagraph::size_type RowLast(Row const * row) const;
625         ///
626         LyXParagraph::size_type RowLastPrintable(Row const * row) const;
627
628         ///
629         void charInserted();
630         //
631         // special owner functions
632         ///
633         LyXParagraph * OwnerParagraph() const;
634         //
635         LyXParagraph * OwnerParagraph(LyXParagraph *) const;
636 };
637
638
639 /* returns a pointer to the row near the specified y-coordinate
640  * (relative to the whole text). y is set to the real beginning
641  * of this row */
642 inline
643 Row * LyXText::GetRowNearY(int & y) const
644 {
645         // If possible we should optimize this method. (Lgb)
646         Row * tmprow = firstrow;
647         int tmpy = 0;
648         
649         while (tmprow->next() && tmpy + tmprow->height() <= y) {
650                 tmpy += tmprow->height();
651                 tmprow = tmprow->next();
652         }
653         
654         y = tmpy;   // return the real y
655         return tmprow;
656 }
657 #endif