]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
a7d11dbefa54df97101b13ce7d0a63925900d0ba
[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-2001 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 "paragraph.h"
23 #include "layout.h"
24 #include "lyxrow.h"
25 #include "vspace.h"
26
27 class Buffer;
28 class BufferParams;
29 class BufferView;
30 class InsetText;
31
32
33 /**
34   This class holds the mapping between buffer paragraphs and screen rows.
35   */
36 class LyXText {
37 public:
38         ///
39         enum text_status {
40                 ///
41                 UNCHANGED,
42                 ///
43                 NEED_MORE_REFRESH,
44                 ///
45                 NEED_VERY_LITTLE_REFRESH,
46                 ///
47                 CHANGED_IN_DRAW
48         };
49
50         /// Constructor
51         LyXText(BufferView *);
52         ///
53         LyXText(InsetText *);
54    
55         /// Destructor
56         ~LyXText();
57
58         void init(BufferView *);
59         ///
60         mutable int number_of_rows;
61         ///
62         mutable int height;
63         ///
64         mutable unsigned int width;
65         /// the current font settings
66         mutable LyXFont current_font;
67         /// the current font
68         mutable LyXFont real_current_font;
69         /// first visible pixel-row is set from LyXScreen!!!
70         // unsigned is wrong here for text-insets!
71         int first;
72         ///
73         BufferView * bv_owner;
74         ///
75         InsetText * inset_owner;
76         ///
77         UpdatableInset * the_locking_inset;
78
79         ///
80         int getRealCursorX(BufferView *) const;
81         ///
82         LyXFont const getFont(Buffer const *, Paragraph * par,
83                         Paragraph::size_type pos) const;
84         ///
85         void setCharFont(Buffer const *, Paragraph * par,
86                          Paragraph::size_type pos, LyXFont const & font);
87         void setCharFont(BufferView *, Paragraph * par,
88                          Paragraph::size_type pos,
89                          LyXFont const & font, bool toggleall);
90         /// returns a pointer to the very first Paragraph
91         Paragraph * firstParagraph() const;
92   
93         /// what you expect when pressing <enter> at cursor position
94         void breakParagraph(BufferView *, char keep_layout = 0);
95
96         /** set layout over selection and make a total rebreak of
97           those paragraphs
98           */
99         Paragraph * setLayout(BufferView *, LyXCursor & actual_cursor,
100                                  LyXCursor & selection_start,
101                                  LyXCursor & selection_end,
102                                  LyXTextClass::size_type layout);
103         void setLayout(BufferView *, LyXTextClass::size_type layout);
104         
105         /// used in setlayout
106         void makeFontEntriesLayoutSpecific(Buffer const *, Paragraph * par);
107         
108         /** increment depth over selection and make a total rebreak of those 
109           paragraphs
110           */
111         void incDepth(BufferView *);
112         
113         /** decrement depth over selection and make a total rebreak of those  
114           paragraphs */
115         void decDepth(BufferView *);
116
117         /** Get the depth at current cursor position
118          */
119         int getDepth() const { return cursor.par()->getDepth(); }
120         
121         /** set font over selection and make a total rebreak of those
122           paragraphs.
123           toggleall defaults to false.
124           */
125         void setFont(BufferView *, LyXFont const &, bool toggleall = false);
126         
127         /** deletes and inserts again all paragaphs between the cursor
128           and the specified par. The Cursor is needed to set the refreshing
129           parameters. 
130           This function is needed after SetLayout and SetFont etc.
131           */
132         void redoParagraphs(BufferView *, LyXCursor const & cursor,
133                             Paragraph const * end_par) const;
134         ///
135         void redoParagraph(BufferView *) const;
136         
137         ///
138         void toggleFree(BufferView *, LyXFont const &, bool toggleall = false);
139         
140         /** recalculates the heights of all previous rows of the
141             specified paragraph.  needed, if the last characters font
142             has changed.  
143             */
144         void redoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
145         
146         /** forces the redrawing of a paragraph. Needed when manipulating a 
147             right address box
148             */ 
149         void redoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
150         
151         /** insert a character, moves all the following breaks in the 
152           same Paragraph one to the right and make a little rebreak
153           */
154         void insertChar(BufferView *, char c);
155         ///
156         void insertInset(BufferView *, Inset * inset);
157    
158         /** Completes the insertion with a full rebreak.
159             Returns true if something was broken. */
160         bool fullRebreak(BufferView *);
161
162         ///
163         Row * need_break_row;
164         ///
165         mutable int refresh_y;
166         ///
167         int refresh_height;
168         ///
169         int refresh_width;
170         ///
171         int refresh_x;
172         ///
173         mutable Row * refresh_row;
174         ///
175         int refresh_pos;
176         
177         /** wether the screen needs a refresh,
178            starting with refresh_y
179            */
180         mutable text_status status;
181         
182         /** returns a pointer to the row near the specified y-coordinate
183           (relative to the whole text). y is set to the real beginning
184           of this row
185           */ 
186         Row * getRowNearY(int & y) const;
187         
188         /** returns the column near the specified x-coordinate of the row 
189          x is set to the real beginning of this column
190          */ 
191         int getColumnNearX(BufferView *, Row * row,
192                            int & x, bool & boundary) const;
193         
194         /** returns a pointer to a specified row. y is set to the beginning
195          of the row
196          */
197         Row * getRow(Paragraph * par,
198                      Paragraph::size_type pos, int & y) const;
199
200         /** returns the height of a default row, needed  for scrollbar
201          */
202         int defaultHeight() const;
203    
204         /** The cursor.
205           Later this variable has to be removed. There should be now internal
206           cursor in a text (and thus not in a buffer). By keeping this it is
207           (I think) impossible to have several views with the same buffer, but
208           the cursor placed at different places.
209           [later]
210           Since the LyXText now has been moved from Buffer to BufferView
211           it should not be absolutely needed to move the cursor...
212           */
213         mutable LyXCursor cursor;
214
215 #if 0
216         /* the selection cursor */
217         /// 
218         mutable bool selection;
219         ///
220         mutable bool mark_set;
221
222         ///
223         mutable LyXCursor sel_cursor;
224         ///
225         mutable LyXCursor sel_start_cursor;
226         ///
227         mutable LyXCursor sel_end_cursor;
228 #else
229         /** The structrue that keeps track of the selections set. */
230         struct Selection {
231                 bool set() const {
232                         return set_;
233                 }
234                 void set(bool s) {
235                         set_ = s;
236                 }
237                 bool mark() const {
238                         return mark_;
239                 }
240                 void mark(bool m) {
241                         mark_ = m;
242                 }
243                 LyXCursor cursor;
244                 LyXCursor start;
245                 LyXCursor end;
246         private:
247                 bool set_; // former selection
248                 bool mark_; // former mark_set
249                 
250         };
251         mutable Selection selection;
252 #endif
253         /// needed for the toggling
254         LyXCursor last_sel_cursor;
255         ///
256         LyXCursor toggle_cursor;
257         ///
258         LyXCursor toggle_end_cursor;
259    
260         /// need the selection cursor:
261         void setSelection(BufferView *);
262         ///
263         void clearSelection(BufferView *) const;
264         ///
265         string const selectionAsString(Buffer const *) const;
266         
267         /// just selects the word the cursor is in
268         void selectWord(BufferView *);
269
270         /** 'selects" the next word, where the cursor is not in 
271          and returns this word as string. THe cursor will be moved 
272          to the beginning of this word. 
273          With SelectSelectedWord can this be highlighted really
274          */ 
275         string const selectNextWord(BufferView *, float & value) const;
276         ///
277         void selectSelectedWord(BufferView *);
278         ///
279         void setCursor(BufferView *, Paragraph * par,
280                        Paragraph::size_type pos,
281                        bool setfont = true,
282                        bool boundary = false) const;
283         ///
284         void setCursor(BufferView *, LyXCursor &, Paragraph * par,
285                        Paragraph::size_type pos,
286                        bool boundary = false) const;
287         ///
288         void setCursorIntern(BufferView *, Paragraph * par,
289                              Paragraph::size_type pos,
290                              bool setfont = true,
291                              bool boundary = false) const;
292         ///
293         void setCurrentFont(BufferView *) const;
294
295         ///
296         bool isBoundary(Buffer const *, Paragraph * par,
297                         Paragraph::size_type pos) const;
298         ///
299         bool isBoundary(Buffer const *, Paragraph * par,
300                          Paragraph::size_type pos,
301                          LyXFont const & font) const;
302
303         ///
304         void setCursorFromCoordinates(BufferView *, int x, int y) const;
305         ///
306         void setCursorFromCoordinates(BufferView *, LyXCursor &,
307                                       int x, int y) const;
308         ///
309         void cursorUp(BufferView *) const;
310         ///
311         void cursorDown(BufferView *) const;
312         ///
313         void cursorLeft(BufferView *, bool internal = true) const;
314         ///
315         void cursorRight(BufferView *, bool internal = true) const;
316         ///
317         void cursorLeftOneWord(BufferView *) const;
318         ///
319         void cursorRightOneWord(BufferView *) const;
320         ///
321         void cursorUpParagraph(BufferView *) const;
322         ///
323         void cursorDownParagraph(BufferView *) const;
324         ///
325         void cursorHome(BufferView *) const;
326         ///
327         void cursorEnd(BufferView *) const;
328         ///
329         void cursorTab(BufferView *) const;
330         ///
331         void cursorTop(BufferView *) const;
332         ///
333         void cursorBottom(BufferView *) const;
334         ///
335         void Delete(BufferView *);
336         ///
337         void backspace(BufferView *);
338         ///
339         void deleteWordForward(BufferView *);
340         ///
341         void deleteWordBackward(BufferView *);
342         ///
343         void deleteLineForward(BufferView *);
344         ///
345         bool selectWordWhenUnderCursor(BufferView *);
346         ///
347         enum TextCase {
348                 ///
349                 text_lowercase = 0,
350                 ///
351                 text_capitalization = 1,
352                 ///
353                 text_uppercase = 2
354         };
355         /// Change the case of the word at cursor position.
356         void changeWordCase(BufferView *, TextCase action);
357         ///
358         void transposeChars(BufferView const &);
359         
360         /** returns a printed row in a pixmap. The y value is needed to
361           decide, wether it is selected text or not. This is a strange
362           solution but faster.
363          */
364         void getVisibleRow(BufferView *, int y_offset, int x_offset,
365                            Row * row_ptr, int y, bool cleared=false);
366
367         ///
368         void cutSelection(BufferView *, bool = true);
369         ///
370         void copySelection(BufferView *);
371         ///
372         void pasteSelection(BufferView *);
373         ///
374         void copyEnvironmentType();
375         ///
376         void pasteEnvironmentType(BufferView *);
377         ///
378         void insertFootnote();
379         ///
380         void insertMarginpar();
381         ///
382         void insertFigure();
383         ///
384         void insertTabular();
385
386         /** the DTP switches for paragraphs. LyX will store the top settings
387          always in the first physical paragraph, the bottom settings in the
388          last. When a paragraph is broken, the top settings rest, the bottom 
389          settings are given to the new one. So I can make shure, they do not
390          duplicate themself (and you cannnot make dirty things with them! )
391          */ 
392         void setParagraph(BufferView *,
393                           bool line_top, bool line_bottom,
394                           bool pagebreak_top, bool pagebreak_bottom,
395                           VSpace const & space_top,
396                           VSpace const & space_bottom,
397                           LyXAlignment align, 
398                           string labelwidthstring,
399                           bool noindent);
400
401         /* these things are for search and replace */
402
403         /** sets the selection over the number of characters of string,
404           no check!!
405           */
406         void setSelectionOverString(BufferView *, string const & str);
407
408         /** simple replacing. The font of the first selected character
409           is used
410           */
411         void replaceSelectionWithString(BufferView *, string const & str);
412
413         /// needed to insert the selection
414         void insertStringAsLines(BufferView *, string const & str);
415         /// needed to insert the selection
416         void insertStringAsParagraphs(BufferView *, string const & str);
417
418         /// Find next inset of some specified type.
419         bool gotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
420                            string const & contents = string()) const;
421         ///
422
423         /* for the greater insets */
424   
425         /// returns false if inset wasn't found
426         bool updateInset(BufferView *, Inset *);
427         ///
428         void checkParagraph(BufferView *, Paragraph * par,
429                             Paragraph::size_type pos);
430         ///
431         int numberOfCell(Paragraph * par,
432                          Paragraph::size_type pos) const;
433         ///
434         Paragraph * getParFromID(int id);
435
436         // undo functions
437         /// returns false if no undo possible
438         bool textUndo(BufferView *);
439         /// returns false if no redo possible
440         bool textRedo(BufferView *);
441         /// used by TextUndo/TextRedo
442         bool textHandleUndo(BufferView *, Undo * undo);
443         /// makes sure the next operation will be stored
444         void finishUndo();
445         /// this is dangerous and for internal use only
446         void freezeUndo();
447         /// this is dangerous and for internal use only
448         void unFreezeUndo();
449         /// the flag used by FinishUndo();
450         mutable bool undo_finished;
451         /// a flag
452         bool undo_frozen;
453         ///
454         void setUndo(Buffer *, Undo::undo_kind kind,
455                      Paragraph const * before,
456                      Paragraph const * end) const;
457         ///
458         void setRedo(Buffer *, Undo::undo_kind kind,
459                      Paragraph const * before,
460                      Paragraph const * end);
461         ///
462         Undo * createUndo(Buffer *, Undo::undo_kind kind,
463                           Paragraph const * before,
464                           Paragraph const * end) const;
465         /// for external use in lyx_cb.C
466         void setCursorParUndo(Buffer *);
467         ///
468         void removeTableRow(LyXCursor & cursor) const;
469         ///
470         bool isEmptyTableCell() const;
471         ///
472         void toggleAppendix(BufferView *);
473         ///
474         int workWidth(BufferView *) const;
475         ///
476         void computeBidiTables(Buffer const *, Row * row) const;
477
478         /// Maps positions in the visual string to positions in logical string.
479         inline
480         Paragraph::size_type log2vis(Paragraph::size_type pos) const {
481                 if (bidi_start == -1)
482                         return pos;
483                 else
484                         return log2vis_list[pos-bidi_start];
485         }
486
487         /// Maps positions in the logical string to positions in visual string.
488         inline
489         Paragraph::size_type vis2log(Paragraph::size_type pos) const {
490                 if (bidi_start == -1)
491                         return pos;
492                 else
493                         return vis2log_list[pos-bidi_start];
494         }
495         ///
496         inline
497         Paragraph::size_type bidi_level(Paragraph::size_type pos) const {
498                 if (bidi_start == -1)
499                         return 0;
500                 else
501                         return bidi_levels[pos-bidi_start];
502         }       
503         ///
504         inline
505         bool bidi_InRange(Paragraph::size_type pos) const {
506                 return bidi_start == -1 ||
507                         (bidi_start <= pos && pos <= bidi_end);
508         }
509 private:
510         ///
511         void init();
512         ///
513         mutable Row * firstrow;
514         ///
515         mutable Row * lastrow;
516
517         /** Copybuffer for copy environment type.
518           Asger has learned that this should be a buffer-property instead
519           Lgb has learned that 'char' is a lousy type for non-characters
520           */
521         LyXTextClass::size_type copylayouttype;
522
523         /** inserts a new row behind the specified row, increments
524             the touched counters */
525         void insertRow(Row * row, Paragraph * par,
526                        Paragraph::size_type pos) const;
527         /** removes the row and reset the touched counters */
528         void removeRow(Row * row) const;
529
530         /** remove all following rows of the paragraph of the specified row. */
531         void removeParagraph(Row * row) const;
532
533         /** insert the specified paragraph behind the specified row */
534         void insertParagraph(BufferView *,
535                              Paragraph * par, Row * row) const;
536
537         /** appends  the implizit specified paragraph behind the specified row,
538          * start at the implizit given position */
539         void appendParagraph(BufferView *, Row * row) const;
540    
541         ///
542         void breakAgain(BufferView *, Row * row) const;
543         ///
544         void breakAgainOneRow(BufferView *, Row * row);
545         /// Calculate and set the height of the row
546         void setHeightOfRow(BufferView *, Row * row_ptr) const;
547
548         /** this calculates the specified parameters. needed when setting
549          * the cursor and when creating a visible row */ 
550         void prepareToPrint(BufferView *, Row * row, float & x,
551                             float & fill_separator, 
552                             float & fill_hfill,
553                             float & fill_label_hfill,
554                             bool bidi = true) const;
555
556         ///
557         void deleteEmptyParagraphMechanism(BufferView *,
558                                            LyXCursor const & old_cursor) const;
559
560         /** Updates all counters starting BEHIND the row. Changed paragraphs
561          * with a dynamic left margin will be rebroken. */ 
562         void updateCounters(BufferView *, Row * row) const;
563         ///
564         void setCounter(Buffer const *, Paragraph * par) const;
565    
566         /*
567          * some low level functions
568          */
569         
570         ///
571         int singleWidth(BufferView *, Paragraph * par,
572                         Paragraph::size_type pos) const;
573         ///
574         int singleWidth(BufferView *, Paragraph * par,
575                         Paragraph::size_type pos, char c) const;
576         ///
577         void draw(BufferView *, Row const * row,
578                   Paragraph::size_type & pos,
579                   int offset, float & x, bool cleared);
580
581         /// get the next breakpoint in a given paragraph
582         Paragraph::size_type nextBreakPoint(BufferView *, Row const * row,
583                                                int width) const;
584         /// returns the minimum space a row needs on the screen in pixel
585         int fill(BufferView *, Row * row, int workwidth) const;
586         
587         /** returns the minimum space a manual label needs on the
588           screen in pixel */ 
589         int labelFill(BufferView *, Row const * row) const;
590
591         ///
592         Paragraph::size_type
593         beginningOfMainBody(Buffer const *, Paragraph const * par) const;
594         
595         /** Returns the left beginning of the text.
596           This information cannot be taken from the layouts-objekt, because
597           in LaTeX the beginning of the text fits in some cases
598           (for example sections) exactly the label-width.
599           */
600         int leftMargin(BufferView *, Row const * row) const;
601         ///
602         int rightMargin(Buffer const *, Row const * row) const;
603         ///
604         int labelEnd (BufferView *, Row const * row) const;
605
606         /** returns the number of separators in the specified row.
607           The separator on the very last column doesnt count
608           */ 
609         int numberOfSeparators(Buffer const *, Row const * row) const;
610
611         /** returns the number of hfills in the specified row. The
612           LyX-Hfill is a LaTeX \hfill so that the hfills at the
613           beginning and at the end were ignored. This is {\em MUCH}
614           more usefull than not to ignore!
615           */
616         int numberOfHfills(Buffer const *, Row const * row) const;
617    
618         /// like NumberOfHfills, but only those in the manual label!
619         int numberOfLabelHfills(Buffer const *, Row const * row) const;
620         /** returns true, if a expansion is needed. Rules are given by 
621           LaTeX
622           */
623         bool hfillExpansion(Buffer const *, Row const * row_ptr,
624                             Paragraph::size_type pos) const;
625
626
627         ///
628         mutable std::vector<Paragraph::size_type> log2vis_list;
629
630         ///
631         mutable std::vector<Paragraph::size_type> vis2log_list;
632
633         ///
634         mutable std::vector<Paragraph::size_type> bidi_levels;
635
636         ///
637         mutable Paragraph::size_type bidi_start;
638
639         ///
640         mutable Paragraph::size_type bidi_end;
641
642         ///
643         mutable bool bidi_same_direction;
644
645         ///
646         unsigned char transformChar(unsigned char c, Paragraph * par,
647                                     Paragraph::size_type pos) const;
648
649         /** returns the paragraph position of the last character in the 
650           specified row
651           */
652         Paragraph::size_type rowLast(Row const * row) const;
653         ///
654         Paragraph::size_type rowLastPrintable(Row const * row) const;
655
656         ///
657         void charInserted();
658         //
659         // special owner functions
660         ///
661         Paragraph * ownerParagraph() const;
662         //
663         Paragraph * ownerParagraph(Paragraph *) const;
664 };
665
666
667 /* returns a pointer to the row near the specified y-coordinate
668  * (relative to the whole text). y is set to the real beginning
669  * of this row */
670 inline
671 Row * LyXText::getRowNearY(int & y) const
672 {
673         // If possible we should optimize this method. (Lgb)
674         Row * tmprow = firstrow;
675         int tmpy = 0;
676         
677         while (tmprow->next() && tmpy + tmprow->height() <= y) {
678                 tmpy += tmprow->height();
679                 tmprow = tmprow->next();
680         }
681         
682         y = tmpy;   // return the real y
683         return tmprow;
684 }
685 #endif