]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
Make LFUN_QUOTE work for InsetText.
[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 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         LyXFont const GetFont(Buffer const *, LyXParagraph * par,
80                         LyXParagraph::size_type pos) const;
81         ///
82         void SetCharFont(Buffer const *, LyXParagraph * par,
83                          LyXParagraph::size_type pos,
84                          LyXFont const & font);
85         /// returns a pointer to the very first LyXParagraph
86         LyXParagraph * FirstParagraph() const;
87   
88         /// what you expect when pressing <enter> at cursor position
89         void BreakParagraph(BufferView *, char keep_layout = 0);
90
91         /** set layout over selection and make a total rebreak of
92           those paragraphs
93           */
94         LyXParagraph * SetLayout(BufferView *, LyXCursor & actual_cursor,
95                                  LyXCursor & selection_start,
96                                  LyXCursor & selection_end,
97                                  LyXTextClass::size_type layout);
98         void SetLayout(BufferView *, LyXTextClass::size_type layout);
99         
100         /// used in setlayout
101         void MakeFontEntriesLayoutSpecific(Buffer const *, LyXParagraph * par);
102         
103         /** increment depth over selection and make a total rebreak of those 
104           paragraphs
105           */
106         void IncDepth(BufferView *);
107         
108         /** decrement depth over selection and make a total rebreak of those  
109           paragraphs */
110         void DecDepth(BufferView *);
111
112         /** Get the depth at current cursor position
113          */
114         int GetDepth() const { return cursor.par()->GetDepth(); }
115         
116         /** set font over selection and make a total rebreak of those
117           paragraphs.
118           toggleall defaults to false.
119           */
120         void SetFont(BufferView *, LyXFont const &, bool toggleall = false);
121         
122         /** deletes and inserts again all paragaphs between the cursor
123           and the specified par. The Cursor is needed to set the refreshing
124           parameters. 
125           This function is needed after SetLayout and SetFont etc.
126           */
127         void RedoParagraphs(BufferView *, LyXCursor const & cursor,
128                             LyXParagraph const * end_par) const;
129         ///
130         void RedoParagraph(BufferView *) const;
131         
132         ///
133         void ToggleFree(BufferView *, LyXFont const &, bool toggleall = false);
134         
135         /** recalculates the heights of all previous rows of the
136             specified paragraph.  needed, if the last characters font
137             has changed.  
138             */
139         void RedoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
140         
141         /** forces the redrawing of a paragraph. Needed when manipulating a 
142             right address box
143             */ 
144         void RedoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
145         
146         /** insert a character, moves all the following breaks in the 
147           same Paragraph one to the right and make a little rebreak
148           */
149         void InsertChar(BufferView *, char c);
150         ///
151         void InsertInset(BufferView *, Inset * inset);
152    
153         /** Completes the insertion with a full rebreak.
154             Returns true if something was broken. */
155         bool FullRebreak(BufferView *);
156
157 #ifndef NEW_INSETS
158         ///
159         LyXParagraph::footnote_flag GetFootnoteFlag(int row);
160 #endif
161         ///
162         Row * need_break_row;
163         ///
164         mutable int refresh_y;
165         ///
166         int refresh_height;
167         ///
168         int refresh_width;
169         ///
170         int refresh_x;
171         ///
172         mutable Row * refresh_row;
173         ///
174         int refresh_pos;
175         
176         /** wether the screen needs a refresh,
177            starting with refresh_y
178            */
179         mutable text_status status;
180         
181         /** returns a pointer to the row near the specified y-coordinate
182           (relative to the whole text). y is set to the real beginning
183           of this row
184           */ 
185         Row * GetRowNearY(int & y) const;
186         
187         /** returns the column near the specified x-coordinate of the row 
188          x is set to the real beginning of this column
189          */ 
190         int GetColumnNearX(BufferView *, Row * row,
191                            int & x, bool & boundary) const;
192         
193         /** returns a pointer to a specified row. y is set to the beginning
194          of the row
195          */
196         Row * GetRow(LyXParagraph * par,
197                      LyXParagraph::size_type pos, int & y) const;
198
199         /** returns the height of a default row, needed  for scrollbar
200          */
201         int DefaultHeight() const;
202    
203         /** The cursor.
204           Later this variable has to be removed. There should be now internal
205           cursor in a text (and thus not in a buffer). By keeping this it is
206           (I think) impossible to have several views with the same buffer, but
207           the cursor placed at different places.
208           [later]
209           Since the LyXText now has been moved from Buffer to BufferView
210           it should not be absolutely needed to move the cursor...
211           */
212         mutable LyXCursor cursor;
213    
214         /* the selection cursor */
215         /// 
216         mutable bool selection;
217         ///
218         mutable bool mark_set;
219
220         ///
221         mutable LyXCursor sel_cursor;
222         ///
223         LyXCursor sel_start_cursor;
224         ///
225         mutable LyXCursor sel_end_cursor;
226         /// needed for the toggling
227         LyXCursor last_sel_cursor;
228         ///
229         LyXCursor toggle_cursor;
230         ///
231         LyXCursor toggle_end_cursor;
232    
233         /// need the selection cursor:
234         void SetSelection(BufferView *);
235         ///
236         void ClearSelection() const;
237         ///
238         string const selectionAsString(Buffer const *) const;
239         
240         /// just selects the word the cursor is in
241         void SelectWord(BufferView *);
242
243         /** 'selects" the next word, where the cursor is not in 
244          and returns this word as string. THe cursor will be moved 
245          to the beginning of this word. 
246          With SelectSelectedWord can this be highlighted really
247          */ 
248         string const SelectNextWord(BufferView *, float & value) const;
249         ///
250         void SelectSelectedWord(BufferView *);
251         ///
252         void SetCursor(BufferView *, LyXParagraph * par,
253                        LyXParagraph::size_type pos,
254                        bool setfont = true,
255                        bool boundary = false) const;
256         ///
257         void SetCursor(BufferView *, LyXCursor &, LyXParagraph * par,
258                        LyXParagraph::size_type pos,
259                        bool boundary = false) const;
260         ///
261         void SetCursorIntern(BufferView *, LyXParagraph * par,
262                              LyXParagraph::size_type pos,
263                              bool setfont = true,
264                              bool boundary = false) const;
265         ///
266         void SetCurrentFont(BufferView *) const;
267
268         ///
269         bool IsBoundary(Buffer const *, LyXParagraph * par,
270                         LyXParagraph::size_type pos) const;
271         ///
272         bool IsBoundary(Buffer const *, LyXParagraph * par,
273                          LyXParagraph::size_type pos,
274                          LyXFont const & font) const;
275
276         ///
277         void SetCursorFromCoordinates(BufferView *, int x, int y) const;
278         ///
279         void SetCursorFromCoordinates(BufferView *, LyXCursor &,
280                                       int x, int y) const;
281         ///
282         void CursorUp(BufferView *) const;
283         ///
284         void CursorDown(BufferView *) const;
285         ///
286         void CursorLeft(BufferView *, bool internal = true) const;
287         ///
288         void CursorRight(BufferView *, bool internal = true) const;
289         ///
290         void CursorLeftOneWord(BufferView *) const;
291         ///
292         void CursorRightOneWord(BufferView *) const;
293         ///
294         void CursorUpParagraph(BufferView *) const;
295         ///
296         void CursorDownParagraph(BufferView *) const;
297         ///
298         void CursorHome(BufferView *) const;
299         ///
300         void CursorEnd(BufferView *) const;
301         ///
302         void CursorTab(BufferView *) const;
303         ///
304         void CursorTop(BufferView *) const;
305         ///
306         void CursorBottom(BufferView *) const;
307         ///
308         void Delete(BufferView *);
309         ///
310         void Backspace(BufferView *);
311         ///
312         void DeleteWordForward(BufferView *);
313         ///
314         void DeleteWordBackward(BufferView *);
315         ///
316         void DeleteLineForward(BufferView *);
317         ///
318         bool SelectWordWhenUnderCursor(BufferView *);
319         ///
320         enum TextCase {
321                 ///
322                 text_lowercase = 0,
323                 ///
324                 text_capitalization = 1,
325                 ///
326                 text_uppercase = 2
327         };
328         /// Change the case of the word at cursor position.
329         void ChangeWordCase(BufferView *, TextCase action);
330
331         /** returns a printed row in a pixmap. The y value is needed to
332           decide, wether it is selected text or not. This is a strange
333           solution but faster.
334          */
335         void GetVisibleRow(BufferView *, int y_offset, int x_offset,
336                            Row * row_ptr, int y, bool cleared=false);
337
338 #ifndef NEW_INSETS
339         /* footnotes: */
340         ///
341         void ToggleFootnote(BufferView *);
342         ///
343         void OpenStuff(BufferView *);
344         ///
345         void OpenFootnotes();
346         ///
347         void OpenFootnote(BufferView *);
348         ///
349         void CloseFootnotes();
350         ///
351         void CloseFootnote(BufferView *);
352
353         /** turn the selection into a new environment. If there is no
354           selection, create an empty environment
355          */ 
356         void InsertFootnoteEnvironment(BufferView *,
357                                        LyXParagraph::footnote_kind kind);
358         ///
359         void MeltFootnoteEnvironment(BufferView *);
360 #endif
361         ///
362         void CutSelection(BufferView *, bool = true);
363         ///
364         void CopySelection(BufferView *);
365         ///
366         void PasteSelection(BufferView *);
367         ///
368         void copyEnvironmentType();
369         ///
370         void pasteEnvironmentType(BufferView *);
371         ///
372         void InsertFootnote();
373         ///
374         void InsertMarginpar();
375         ///
376         void InsertFigure();
377         ///
378         void InsertTabular();
379
380         /** the DTP switches for paragraphs. LyX will store the top settings
381          always in the first physical paragraph, the bottom settings in the
382          last. When a paragraph is broken, the top settings rest, the bottom 
383          settings are given to the new one. So I can make shure, they do not
384          duplicate themself (and you cannnot make dirty things with them! )
385          */ 
386         void SetParagraph(BufferView *,
387                           bool line_top, bool line_bottom,
388                           bool pagebreak_top, bool pagebreak_bottom,
389                           VSpace const & space_top,
390                           VSpace const & space_bottom,
391                           LyXAlignment align, 
392                           string labelwidthstring,
393                           bool noindent);
394         ///
395         void SetParagraphExtraOpt(BufferView *, int type,
396                                   string const & width,
397                                   string const & widthp,
398                                   int alignment, bool hfill,
399                                   bool start_minipage);
400
401         /* these things are for search and replace */
402
403         /** returns true if the specified string is at the specified
404           position
405           */
406         bool IsStringInText(LyXParagraph * par,
407                             LyXParagraph::size_type pos,
408                             string const & str) const;
409         /** sets the selection over the number of characters of string,
410           no check!!
411           */
412         void SetSelectionOverString(BufferView *, string const & str);
413
414         /** simple replacing. The font of the first selected character
415           is used
416           */
417         void ReplaceSelectionWithString(BufferView *, string const & str);
418
419         /** if the string can be found: return true and set the cursor to
420           the new position */
421         bool SearchForward(BufferView *, string const & str) const;
422         ///
423         bool SearchBackward(BufferView *, string const & str) const;
424
425         /// needed to insert the selection
426         void InsertStringA(BufferView *, string const & str);
427         /// needed to insert the selection
428         void InsertStringB(BufferView *, string const & str);
429
430         /// Find next inset of some specified type.
431         bool GotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
432                            string const & contents = string()) const;
433         ///
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         LyXParagraph::size_type 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