]> git.lyx.org Git - features.git/blob - src/lyxtext.h
408965d3b689546e4c57f959584d19b5dd0373a6
[features.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, 
303                            Row * row_ptr, long y);
304                                            
305         /* footnotes: */
306         ///
307         void ToggleFootnote();
308         ///
309         void OpenStuff();
310         ///
311         void OpenFootnotes();
312         ///
313         void OpenFootnote();
314         ///
315         void CloseFootnotes();
316         ///
317         void CloseFootnote();
318
319         /** turn the selection into a new environment. If there is no
320           selection, create an empty environment
321          */ 
322         void InsertFootnoteEnvironment(LyXParagraph::footnote_kind kind);
323         ///
324         void MeltFootnoteEnvironment();
325         ///
326         void CutSelection(bool = true);
327         ///
328         void CopySelection();
329         ///
330         void PasteSelection();
331         ///
332         void copyEnvironmentType();
333         ///
334         void pasteEnvironmentType();
335         ///
336         void InsertFootnote();
337         ///
338         void InsertMarginpar();
339         ///
340         void InsertFigure();
341         ///
342         void InsertTabular();
343
344         /** the DTP switches for paragraphs. LyX will store the top settings
345          always in the first physical paragraph, the bottom settings in the
346          last. When a paragraph is broken, the top settings rest, the bottom 
347          settings are given to the new one. So I can make shure, they do not
348          duplicate themself (and you cannnot make dirty things with them! )
349          */ 
350         void SetParagraph(bool line_top, bool line_bottom,
351                           bool pagebreak_top, bool pagebreak_bottom,
352                           VSpace const & space_top,
353                           VSpace const & space_bottom,
354                           LyXAlignment align, 
355                           string labelwidthstring,
356                           bool noindent);
357         void SetParagraphExtraOpt(int type,
358                                   char const * width,
359                                   char const * widthp,
360                                   int alignment, bool hfill,
361                                   bool start_minipage);
362
363         /* these things are for search and replace */
364
365         /** returns true if the specified string is at the specified
366           position
367           */
368         bool IsStringInText(LyXParagraph * par,
369                             LyXParagraph::size_type pos,
370                             char const * str) const;
371         /** sets the selection over the number of characters of string,
372           no check!!
373           */
374         void SetSelectionOverString(char const * str);
375
376         /** simple replacing. The font of the first selected character
377           is used
378           */
379         void ReplaceSelectionWithString(char const * str);
380
381         /** if the string can be found: return true and set the cursor to
382           the new position */
383         bool SearchForward(char const * str) const;
384         bool SearchBackward(char const * str) const;
385
386         /// needed to insert the selection
387         void InsertStringA(string const & str);
388         /// needed to insert the selection
389         void InsertStringB(string const & str);
390
391         /// usefull when texing from within LyX
392         bool GotoNextError() const;
393
394         /// just another feature :)
395         bool GotoNextNote() const;
396
397         /** needed to switch between different classes this works
398           for a list of paragraphs beginning with the specified par 
399           return value is the number of wrong conversions
400           */ 
401         int SwitchLayoutsBetweenClasses(LyXTextClassList::size_type class1,
402                                         LyXTextClassList::size_type class2,
403                                         LyXParagraph * par);
404
405         /* for the greater insets */
406   
407         /// returns 0 if inset wasn't found
408         int UpdateInset(Inset * inset);
409         ///
410         void CheckParagraph(LyXParagraph * par,
411                             LyXParagraph::size_type pos);
412         ///
413         int NumberOfCell(LyXParagraph * par,
414                          LyXParagraph::size_type pos) const;
415         /* table stuff -- begin*/
416
417         /** all table features of the text-class are put together in
418           this function. Possible values of feature are defined in table.h
419           */
420         void TableFeatures(int feature, string const & val) const;
421         ///
422         void TableFeatures(int feature) const;
423
424         /** pos points at the beginning of the next cell (if there is one)
425          */
426         int WidthOfCell(LyXParagraph * par,
427                         LyXParagraph::size_type & pos) const;
428         ///
429         void CheckParagraphInTable(LyXParagraph * par,
430                                    LyXParagraph::size_type pos);
431         ///
432         void InsertCharInTable(char c);
433         ///
434         void BackspaceInTable();
435         ///
436         bool HitInTable(Row * row, int x) const;
437         ///
438         bool MouseHitInTable(int x, long y) const;
439         /* table stuff -- end*/
440         ///
441         LyXParagraph * GetParFromID(int id);
442
443         // undo functions
444         /// returns false if no undo possible
445         bool TextUndo();
446         /// returns false if no redo possible
447         bool TextRedo();
448         /// used by TextUndo/TextRedo
449         bool TextHandleUndo(Undo * undo);
450         /// makes sure the next operation will be stored
451         void FinishUndo();
452         /// this is dangerous and for internal use only
453         void FreezeUndo();
454         /// this is dangerous and for internal use only
455         void UnFreezeUndo();
456         /// the flag used by FinishUndo();
457         mutable bool undo_finished;
458         /// a flag
459         bool undo_frozen;
460         ///
461         void SetUndo(Undo::undo_kind kind,
462                      LyXParagraph const * before,
463                      LyXParagraph const * end) const;
464         ///
465         void SetRedo(Undo::undo_kind kind,
466                      LyXParagraph const * before,
467                      LyXParagraph const * end);
468         ///
469         Undo * CreateUndo(Undo::undo_kind kind,
470                           LyXParagraph const * before,
471                           LyXParagraph const * end) const;
472         /// for external use in lyx_cb.C
473         void SetCursorParUndo();
474         ///
475         void CursorLeftIntern() const;
476         ///
477         void CursorRightIntern() const;
478         ///
479         void RemoveTableRow(LyXCursor * cursor) const;
480         ///
481         bool IsEmptyTableCell() const;
482         ///
483         void toggleAppendix();
484         ///
485         unsigned short paperWidth() const { return paperwidth; }
486 private:
487         ///
488         BufferView * owner_;
489         
490         /// width of the paper
491         unsigned short  paperwidth;
492
493         ///
494         mutable Row * firstrow;
495         ///
496         mutable Row * lastrow;
497         
498         /** Copybuffer for copy environment type
499           Asger has learned that this should be a buffer-property instead
500           Lgb has learned that 'char' is a lousy type for non-characters
501           */
502         LyXTextClass::size_type copylayouttype;
503
504         /// the currentrow is needed to access rows faster*/ 
505         mutable Row * currentrow; // pointer to the current row
506         /// position in the text 
507         mutable long currentrow_y;
508    
509         /** inserts a new row behind the specified row, increments
510          * the touched counters */
511         void InsertRow(Row * row, LyXParagraph * par,
512                        LyXParagraph::size_type pos) const;
513         /** removes the row and reset the touched counters */
514         void RemoveRow(Row * row) const;
515
516         /** remove all following rows of the paragraph of the specified row. */
517         void RemoveParagraph(Row * row) const;
518
519         /** insert the specified paragraph behind the specified row */
520         void InsertParagraph(LyXParagraph * par, Row * row) const;
521
522         /** appends  the implizit specified paragraph behind the specified row,
523          * start at the implizit given position */
524         void AppendParagraph(Row * row) const;
525    
526         ///
527         void BreakAgain(Row * row) const;
528         ///
529         void BreakAgainOneRow(Row * row);
530         /// Calculate and set the height of the row
531         void SetHeightOfRow(Row * row_ptr) const;
532
533         /** this calculates the specified parameters. needed when setting
534          * the cursor and when creating a visible row */ 
535         void PrepareToPrint(Row * row, float & x,
536                             float & fill_separator, 
537                             float & fill_hfill,
538                             float & fill_label_hfill,
539                             bool bidi = true) const;
540         ///
541         void DeleteEmptyParagraphMechanism(LyXCursor const & old_cursor) const;
542
543         /** Updates all counters starting BEHIND the row. Changed paragraphs
544          * with a dynamic left margin will be rebroken. */ 
545         void UpdateCounters(Row * row) const;
546         ///
547         void SetCounter(LyXParagraph * par) const;
548    
549         /*
550          * some low level functions
551          */
552         
553         ///
554         int SingleWidth(LyXParagraph * par,
555                         LyXParagraph::size_type pos) const;
556         ///
557         int SingleWidth(LyXParagraph * par,
558                         LyXParagraph::size_type pos, char c) const;
559         ///
560         void draw(Row const * row,
561                   LyXParagraph::size_type & pos,
562                   int offset, float & x);
563
564         /// get the next breakpoint in a given paragraph
565         LyXParagraph::size_type NextBreakPoint(Row const * row,
566                                                int width) const;
567         /// returns the minimum space a row needs on the screen in pixel
568         int Fill(Row const * row, int paperwidth) const;
569         
570         /** returns the minimum space a manual label needs on the
571           screen in pixel */ 
572         int LabelFill(Row const * row) const;
573
574         ///
575         LyXParagraph::size_type BeginningOfMainBody(LyXParagraph * par) const;
576         
577         /** Returns the left beginning of the text.
578           This information cannot be taken from the layouts-objekt, because
579           in LaTeX the beginning of the text fits in some cases
580           (for example sections) exactly the label-width.
581           */
582         int LeftMargin(Row const * row) const;
583         ///
584         int RightMargin(Row const * row) const;
585         ///
586         int LabelEnd (Row const * row) const;
587
588         /** returns the number of separators in the specified row.
589           The separator on the very last column doesnt count
590           */ 
591         int NumberOfSeparators(Row const * row) const;
592
593         /** returns the number of hfills in the specified row. The
594           LyX-Hfill is a LaTeX \hfill so that the hfills at the
595           beginning and at the end were ignored. This is {\em MUCH}
596           more usefull than not to ignore!
597           */
598         int NumberOfHfills(Row const * row) const;
599    
600         /// like NumberOfHfills, but only those in the manual label!
601         int NumberOfLabelHfills(Row const * row) const;
602
603         /** returns true, if a expansion is needed. Rules are given by 
604           LaTeX
605           */
606         bool HfillExpansion(Row const * row_ptr,
607                             LyXParagraph::size_type pos) const;
608
609         ///
610         mutable vector<LyXParagraph::size_type> log2vis_list;
611
612         ///
613         mutable vector<LyXParagraph::size_type> vis2log_list;
614
615         ///
616         mutable LyXParagraph::size_type bidi_start;
617
618         ///
619         void ComputeBidiTables(Row *row) const;
620
621         ///
622         void ComputeBidiTablesFromTo(Row *row,
623                                      LyXParagraph::size_type from,
624                                      LyXParagraph::size_type to,
625                                      LyXParagraph::size_type offset) const;
626
627         /// Maps positions in the visual string to positions in logical string.
628         inline
629         LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const {
630                 if (bidi_start == -1)
631                         return pos;
632                 else
633                         return log2vis_list[pos-bidi_start];
634         }
635
636         /// Maps positions in the logical string to positions in visual string.
637         inline
638         LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const {
639                 if (bidi_start == -1)
640                         return pos;
641                 else
642                         return vis2log_list[pos-bidi_start];
643         }
644
645         ///
646         unsigned char TransformChar(unsigned char c, Letter_Form form) const;
647
648         ///
649         unsigned char TransformChar(unsigned char c, LyXParagraph * par,
650                                 LyXParagraph::size_type pos) const;
651
652         /** returns the paragraph position of the last character in the 
653           specified row
654           */
655         LyXParagraph::size_type RowLast(Row const * row) const;
656         ///
657         void charInserted();
658 };
659
660 #endif