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