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