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