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