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