]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
Ding dong, the CID is dead...
[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-2001 The LyX Team.
9  *
10  * ====================================================== */
11
12 #ifndef LYXTEXT_H
13 #define LYXTEXT_H
14
15 #include "lyxfont.h"
16 #include "lyxcursor.h"
17 #include "layout.h"
18 #include "LColor.h"
19 #include "insets/inset.h"
20
21 class Buffer;
22 class BufferParams;
23 class BufferView;
24 class InsetText;
25 class Paragraph;
26 class Row;
27 class Spacing;
28 class UpdatableInset;
29 class VSpace;
30 class WordLangTuple;
31 class ParagraphList;
32
33
34 /**
35   This class holds the mapping between buffer paragraphs and screen rows.
36   */
37 class LyXText {
38 public:
39         /// what repainting is needed
40         enum text_status {
41                 /// no repaint is needed
42                 UNCHANGED = 0,
43                 /// the refresh_row needs repainting
44                 NEED_VERY_LITTLE_REFRESH = 1,
45                 /// everything from refresh_y downwards needs repainting
46                 NEED_MORE_REFRESH = 2
47         };
48
49         ///
50         enum word_location {
51                 // the word around the cursor, only if the cursor is
52                 //not at a boundary
53                 WHOLE_WORD_STRICT,
54                 // the word around the cursor
55                 WHOLE_WORD,
56                 /// the word begining from the cursor position
57                 PARTIAL_WORD,
58                 /// the word around the cursor or before the cursor
59                 PREVIOUS_WORD,
60                 /// the next word (not yet used)
61                 NEXT_WORD
62         };
63
64         /// Constructor
65         LyXText(BufferView *);
66         /// sets inset as owner
67         LyXText(BufferView *, InsetText *);
68
69         /// Destructor
70         ~LyXText();
71
72         void init(BufferView *, bool reinit = false);
73         ///
74         int height;
75         ///
76         unsigned int width;
77         /// the current font settings
78         LyXFont current_font;
79         /// the current font
80         LyXFont real_current_font;
81 private:
82         /** the 'anchor' row: the position of this row remains constant
83          *  with respect to the top of the screen
84          */
85         Row * anchor_row_;
86         /** the pixel offset with respect to this row of top_y
87          */
88         int anchor_row_offset_;
89 public:
90         /// get the y coord. of the top of the screen (relative to doc start)
91         int top_y() const;
92         /// set the y coord. of the top of the screen (relative to doc start)
93         void top_y(int newy);
94         /// set the anchoring row. top_y will be computed relative to this
95         void anchor_row(Row * row);
96         ///
97         InsetText * inset_owner;
98         ///
99         UpdatableInset * the_locking_inset;
100
101         ///
102         int getRealCursorX() const;
103         ///
104         LyXFont const getFont(Buffer const *, Paragraph * par,
105                 lyx::pos_type pos) const;
106         ///
107         LyXFont const getLayoutFont(Buffer const *, Paragraph * par) const;
108         ///
109         LyXFont const getLabelFont(Buffer const *, Paragraph * par) const;
110         ///
111         void setCharFont(Buffer const *, Paragraph * par,
112                          lyx::pos_type pos, LyXFont const & font);
113         void setCharFont(Paragraph * par,
114                          lyx::pos_type pos, LyXFont const & font, bool toggleall);
115
116         ///
117         void breakAgainOneRow(Row * row);
118         /// what you expect when pressing <enter> at cursor position
119         void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
120
121         /** set layout over selection and make a total rebreak of
122           those paragraphs
123           */
124         Paragraph * setLayout(LyXCursor & actual_cursor,
125                               LyXCursor & selection_start,
126                               LyXCursor & selection_end,
127                               string const & layout);
128         ///
129         void setLayout(string const & layout);
130
131         /** increment depth over selection and make a total rebreak of those
132           paragraphs
133           */
134         void incDepth();
135
136         /** decrement depth over selection and make a total rebreak of those
137           paragraphs */
138         void decDepth();
139
140         /// get the depth at current cursor position
141         int getDepth() const;
142
143         /** set font over selection and make a total rebreak of those
144           paragraphs.
145           toggleall defaults to false.
146           */
147         void setFont(LyXFont const &, bool toggleall = false);
148
149         /** deletes and inserts again all paragaphs between the cursor
150           and the specified par. The Cursor is needed to set the refreshing
151           parameters.
152           This function is needed after SetLayout and SetFont etc.
153           */
154         void redoParagraphs(LyXCursor const & cursor,
155                             Paragraph const * end_par);
156         ///
157         void redoParagraph();
158
159         ///
160         void toggleFree(LyXFont const &, bool toggleall = false);
161
162         ///
163         string getStringToIndex();
164
165         /** recalculates the heights of all previous rows of the
166             specified paragraph.  needed, if the last characters font
167             has changed.
168             */
169         void redoHeightOfParagraph();
170
171         /** insert a character, moves all the following breaks in the
172           same Paragraph one to the right and make a little rebreak
173           */
174         void insertChar(char c);
175         ///
176         void insertInset(Inset * inset);
177
178         /// Completes the insertion with a full rebreak
179         void fullRebreak();
180
181         ///
182         Row * need_break_row;
183
184         /// clear any pending paints
185         void clearPaint();
186
187         /**
188          * Mark position y as the starting point for a repaint
189          */
190         void postPaint(int start_y);
191
192         /**
193          * Mark the given row at position y as needing a repaint.
194          */
195         void postRowPaint(Row * row, int start_y);
196
197         ///
198         Inset::RESULT dispatch(FuncRequest const & cmd);
199
200         BufferView * bv();
201
202         BufferView * bv() const;
203
204         friend class LyXScreen;
205
206         /**
207          * Return the status. This represents what repaints are
208          * pending after some operation (e.g. inserting a char).
209          */
210         text_status status() const;
211
212 private:
213         /**
214          * The pixel y position from which to repaint the screen.
215          * The position is absolute along the height of outermost
216          * lyxtext (I think). NEED_MORE_REFRESH and NEED_LITTLE_REFRESH
217          * repaints both use this as a starting point (if it's within
218          * the viewable portion of the lyxtext).
219          */
220         int refresh_y;
221         /**
222          * The row from which to repaint the screen, used by screen.c.
223          * This must be set if the pending update is NEED_LITTLE_REFRESH.
224          * It doesn't make any difference for NEED_MORE_REFRESH.
225          */
226         Row * refresh_row;
227
228         /// refresh status
229         text_status status_;
230
231         /// only the top-level LyXText has this non-zero
232         BufferView * bv_owner;
233
234 public:
235         /** returns a pointer to the row near the specified y-coordinate
236           (relative to the whole text). y is set to the real beginning
237           of this row
238           */
239         Row * getRowNearY(int & y) const;
240
241         /** returns the column near the specified x-coordinate of the row
242          x is set to the real beginning of this column
243          */
244         lyx::pos_type getColumnNearX(Row * row,
245                                             int & x, bool & boundary) const;
246
247         /** returns a pointer to a specified row. y is set to the beginning
248          of the row
249          */
250         Row * getRow(Paragraph * par, lyx::pos_type pos, int & y) const;
251         /** returns the firstrow, this could be done with the above too but
252             IMO it's stupid to have to allocate a dummy y all the time I need
253             the first row
254         */
255         Row * firstRow() const { return firstrow; }
256
257         /** The cursor.
258           Later this variable has to be removed. There should be now internal
259           cursor in a text (and thus not in a buffer). By keeping this it is
260           (I think) impossible to have several views with the same buffer, but
261           the cursor placed at different places.
262           [later]
263           Since the LyXText now has been moved from Buffer to BufferView
264           it should not be absolutely needed to move the cursor...
265           */
266         LyXCursor cursor; // actual cursor position
267
268         /** The structure that keeps track of the selections set. */
269         struct Selection {
270                 Selection()
271                         : set_(false), mark_(false)
272                         {}
273                 bool set() const {
274                         return set_;
275                 }
276                 void set(bool s) {
277                         set_ = s;
278                 }
279                 bool mark() const {
280                         return mark_;
281                 }
282                 void mark(bool m) {
283                         mark_ = m;
284                 }
285                 LyXCursor cursor; // temporary cursor to hold a cursor position
286                                   // until setSelection is called!
287                 LyXCursor start;  // start of a REAL selection
288                 LyXCursor end;    // end of a REAL selection
289         private:
290                 bool set_; // former selection
291                 bool mark_; // former mark_set
292
293         };
294         Selection selection;
295         // this is used to handle XSelection events in the right manner
296         Selection xsel_cache;
297
298         /// needed for the toggling (cursor position on last selection made)
299         LyXCursor last_sel_cursor;
300         /// needed for toggling the selection in screen.C
301         LyXCursor toggle_cursor;
302         /// needed for toggling the selection in screen.C
303         LyXCursor toggle_end_cursor;
304
305         /// need the selection cursor:
306         void setSelection();
307         ///
308         void clearSelection();
309         ///
310         string const selectionAsString(Buffer const *, bool label) const;
311
312         /// select the word we need depending on word_location
313         void getWord(LyXCursor & from, LyXCursor & to,
314                      word_location const);
315         /// just selects the word the cursor is in
316         void selectWord(word_location const);
317         /// returns the inset at cursor (if it exists), 0 otherwise
318         Inset * getInset() const;
319
320         /// accept selected change
321         void acceptChange();
322
323         /// reject selected change
324         void rejectChange();
325
326         /** 'selects" the next word, where the cursor is not in
327          and returns this word as string. THe cursor will be moved
328          to the beginning of this word.
329          With SelectSelectedWord can this be highlighted really
330          */
331         WordLangTuple const selectNextWordToSpellcheck(float & value);
332         ///
333         void selectSelectedWord();
334         /// returns true if par was empty and was removed
335         bool setCursor(Paragraph * par,
336                        lyx::pos_type pos,
337                        bool setfont = true,
338                        bool boundary = false);
339         ///
340         void setCursor(LyXCursor &, Paragraph * par,
341                        lyx::pos_type pos,
342                        bool boundary = false);
343         ///
344         void setCursorIntern(Paragraph * par,
345                              lyx::pos_type pos,
346                              bool setfont = true,
347                              bool boundary = false);
348         ///
349         void setCurrentFont();
350
351         ///
352         bool isBoundary(Buffer const *, Paragraph * par,
353                         lyx::pos_type pos) const;
354         ///
355         bool isBoundary(Buffer const *, Paragraph * par,
356                          lyx::pos_type pos,
357                          LyXFont const & font) const;
358
359         ///
360         void setCursorFromCoordinates(int x, int y);
361         ///
362         void setCursorFromCoordinates(LyXCursor &,
363                                       int x, int y);
364         ///
365         void cursorUp(bool selecting = false);
366         ///
367         void cursorDown(bool selecting = false);
368         ///
369         void cursorLeft(bool internal = true);
370         ///
371         void cursorRight(bool internal = true);
372         ///
373         void cursorLeftOneWord();
374         ///
375         void cursorRightOneWord();
376         ///
377         void cursorUpParagraph();
378         ///
379         void cursorDownParagraph();
380         ///
381         void cursorHome();
382         ///
383         void cursorEnd();
384         ///
385         void cursorPrevious();
386         ///
387         void cursorNext();
388         ///
389         void cursorTab();
390         ///
391         void cursorTop();
392         ///
393         void cursorBottom();
394         ///
395         void Delete();
396         ///
397         void backspace();
398         ///
399         bool selectWordWhenUnderCursor(word_location);
400         ///
401         enum TextCase {
402                 ///
403                 text_lowercase = 0,
404                 ///
405                 text_capitalization = 1,
406                 ///
407                 text_uppercase = 2
408         };
409         /// Change the case of the word at cursor position.
410         void changeCase(TextCase action);
411         ///
412         void transposeChars();
413
414         ///
415         void toggleInset();
416         ///
417         void cutSelection(bool doclear = true, bool realcut = true);
418         ///
419         void copySelection();
420         ///
421         void pasteSelection();
422         ///
423         void copyEnvironmentType();
424         ///
425         void pasteEnvironmentType();
426
427         /** the DTP switches for paragraphs. LyX will store the top settings
428          always in the first physical paragraph, the bottom settings in the
429          last. When a paragraph is broken, the top settings rest, the bottom
430          settings are given to the new one. So I can make shure, they do not
431          duplicate themself (and you cannnot make dirty things with them! )
432          */
433         void setParagraph(bool line_top, bool line_bottom,
434                           bool pagebreak_top, bool pagebreak_bottom,
435                           VSpace const & space_top,
436                           VSpace const & space_bottom,
437                           Spacing const & spacing,
438                           LyXAlignment align,
439                           string const & labelwidthstring,
440                           bool noindent);
441
442         /* these things are for search and replace */
443
444         /**
445          * Sets the selection from the current cursor position to length
446          * characters to the right. No safety checks.
447          */
448         void setSelectionRange(lyx::pos_type length);
449
450         /** simple replacing. The font of the first selected character
451           is used
452           */
453         void replaceSelectionWithString(string const & str);
454
455         /// needed to insert the selection
456         void insertStringAsLines(string const & str);
457         /// needed to insert the selection
458         void insertStringAsParagraphs(string const & str);
459
460         /// Find next inset of some specified type.
461         bool gotoNextInset(std::vector<Inset::Code> const & codes,
462                            string const & contents = string());
463         ///
464         void gotoInset(std::vector<Inset::Code> const & codes,
465                        bool same_content);
466         ///
467         void gotoInset(Inset::Code code, bool same_content);
468         ///
469
470         /* for the greater insets */
471
472         /// returns false if inset wasn't found
473         bool updateInset(Inset *);
474         ///
475         void checkParagraph(Paragraph * par, lyx::pos_type pos);
476         ///
477         int workWidth() const;
478         ///
479         int workWidth(Inset * inset) const;
480
481         ///
482         void computeBidiTables(Buffer const *, Row * row) const;
483         /// Maps positions in the visual string to positions in logical string.
484         lyx::pos_type log2vis(lyx::pos_type pos) const;
485         /// Maps positions in the logical string to positions in visual string.
486         lyx::pos_type vis2log(lyx::pos_type pos) const;
487         ///
488         lyx::pos_type bidi_level(lyx::pos_type pos) const;
489         ///
490         bool bidi_InRange(lyx::pos_type pos) const;
491 private:
492         ///
493         Row * firstrow;
494         ///
495         Row * lastrow;
496
497         ///
498         void cursorLeftOneWord(LyXCursor &);
499
500         ///
501         float getCursorX(Row *, lyx::pos_type pos,
502                          lyx::pos_type last, bool boundary) const;
503         /// used in setlayout
504         void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
505
506         /** forces the redrawing of a paragraph. Needed when manipulating a
507             right address box
508             */
509         void redoDrawingOfParagraph(LyXCursor const & cursor);
510
511         /** Copybuffer for copy environment type.
512           Asger has learned that this should be a buffer-property instead
513           Lgb has learned that 'char' is a lousy type for non-characters
514           */
515         string copylayouttype;
516
517         /** inserts a new row behind the specified row, increments
518             the touched counters */
519         void insertRow(Row * row, Paragraph * par, lyx::pos_type pos);
520         /// removes the row and reset the touched counters
521         void removeRow(Row * row);
522
523         /// remove all following rows of the paragraph of the specified row.
524         void removeParagraph(Row * row);
525
526         /// insert the specified paragraph behind the specified row
527         void insertParagraph(Paragraph * par, Row * row);
528
529         /** appends  the implizit specified paragraph behind the specified row,
530          * start at the implizit given position */
531         void appendParagraph(Row * row);
532
533         ///
534         void breakAgain(Row * row);
535         /// Calculate and set the height of the row
536         void setHeightOfRow(Row * row_ptr);
537
538         // fix the cursor `cur' after a characters has been deleted at `where'
539         // position. Called by deleteEmptyParagraphMechanism
540         void fixCursorAfterDelete(LyXCursor & cur,
541                                   LyXCursor const & where);
542
543         /// delete double space (false) or empty paragraphs (true) around old_cursor
544         bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor);
545
546 public:
547         /** Updates all counters starting BEHIND the row. Changed paragraphs
548          * with a dynamic left margin will be rebroken. */
549         void updateCounters();
550         ///
551         void update();
552         /**
553          * Returns an inset if inset was hit, or 0 if not.
554          * If hit, the coordinates are changed relative to the inset.
555          */
556         Inset * checkInsetHit(int & x, int & y);
557
558         ///
559         int singleWidth(Paragraph * par,
560                 lyx::pos_type pos) const;
561         ///
562         int singleWidth(Paragraph * par,
563                 lyx::pos_type pos, char c) const;
564
565         /// return the color of the canvas
566         LColor::color backgroundColor() const;
567
568         ///
569         mutable bool bidi_same_direction;
570
571         unsigned char transformChar(unsigned char c, Paragraph * par,
572                                     lyx::pos_type pos) const;
573
574         /**
575          * Returns the left beginning of the text.
576          * This information cannot be taken from the layout object, because
577          * in LaTeX the beginning of the text fits in some cases
578          * (for example sections) exactly the label-width.
579          */
580         int leftMargin(Row const * row) const;
581         ///
582         int rightMargin(Buffer const &, Row const & row) const;
583
584         /** this calculates the specified parameters. needed when setting
585          * the cursor and when creating a visible row */
586         void prepareToPrint(Row * row, float & x,
587                             float & fill_separator,
588                             float & fill_hfill,
589                             float & fill_label_hfill,
590                             bool bidi = true) const;
591
592 private:
593         ///
594         void setCounter(Buffer const *, Paragraph * par);
595         ///
596         void deleteWordForward();
597         ///
598         void deleteWordBackward();
599         ///
600         void deleteLineForward();
601
602         /*
603          * some low level functions
604          */
605
606
607         /// return the pos value *before* which a row should break.
608         /// for example, the pos at which IsNewLine(pos) == true
609         lyx::pos_type rowBreakPoint(Row const & row) const;
610
611         /// returns the minimum space a row needs on the screen in pixel
612         int fill(Row & row, int workwidth) const;
613
614         /**
615          * returns the minimum space a manual label needs on the
616          * screen in pixels
617          */
618         int labelFill(Row const & row) const;
619
620         /// FIXME
621         int labelEnd(Row const & row) const;
622
623         ///
624         mutable std::vector<lyx::pos_type> log2vis_list;
625         ///
626         mutable std::vector<lyx::pos_type> vis2log_list;
627         ///
628         mutable std::vector<lyx::pos_type> bidi_levels;
629         ///
630         mutable lyx::pos_type bidi_start;
631         ///
632         mutable lyx::pos_type bidi_end;
633
634         ///
635         void charInserted();
636 public:
637         //
638         // special owner functions
639         ///
640         Paragraph * ownerParagraph() const;
641         //
642         void ownerParagraph(Paragraph *) const;
643         // set it searching first for the right owner using the paragraph id
644         void ownerParagraph(int id, Paragraph *) const;
645
646         /// return true if this is owned by an inset.
647         bool isInInset() const;
648 };
649
650 /// return the default height of a row in pixels, considering font zoom
651 extern int defaultRowHeight();
652
653 #endif // LYXTEXT_H