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