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