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