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