]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
282a12e9b7d4866ab4b78a2bc1bbdc62033f5881
[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 "bufferview_funcs.h"
18 #include "cursor_slice.h"
19 #include "Bidi.h"
20 #include "layout.h"
21 #include "lyxfont.h"
22 #include "lyxtextclass.h"
23 #include "ParagraphList_fwd.h"
24 #include "RowList_fwd.h"
25
26 #include "insets/inset.h"
27
28 #include <iosfwd>
29
30 class Buffer;
31 class BufferParams;
32 class BufferView;
33 class Dimension;
34 class LColor_color;
35 class CursorSlice;
36 class MetricsInfo;
37 class Paragraph;
38 class Row;
39 class Spacing;
40 class UpdatableInset;
41 class VSpace;
42
43
44 // The structure that keeps track of the selections set.
45 struct Selection {
46         Selection()
47                 : set_(false), mark_(false)
48                 {}
49         bool set() const {
50                 return set_;
51         }
52         void set(bool s) {
53                 set_ = s;
54         }
55         bool mark() const {
56                 return mark_;
57         }
58         void mark(bool m) {
59                 mark_ = m;
60         }
61 private:
62         bool set_; // former selection
63         bool mark_; // former mark_set
64 };
65
66
67 /// This class encapsulates the main text data and operations in LyX
68 class LyXText {
69 public:
70         /// Constructor
71         LyXText(BufferView *, bool ininset);
72         ///
73         void init(BufferView *);
74
75
76         /// update y coordinate cache of all paragraphs
77         void updateParPositions();
78         ///
79         LyXFont getFont(ParagraphList::iterator pit, lyx::pos_type pos) const;
80         ///
81         LyXFont getLayoutFont(ParagraphList::iterator pit) const;
82         ///
83         LyXFont getLabelFont(ParagraphList::iterator pit) const;
84         ///
85         void setCharFont(ParagraphList::iterator pit,
86                          lyx::pos_type pos, LyXFont const & font);
87         void setCharFont(ParagraphList::iterator pit,
88                          lyx::pos_type pos,
89                          LyXFont const & font, bool toggleall);
90
91         /// what you expect when pressing <enter> at cursor position
92         void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
93
94         /** set layout over selection and make a total rebreak of
95           those paragraphs
96           */
97         ParagraphList::iterator
98         setLayout(ParagraphList::iterator start,
99                   ParagraphList::iterator end,
100                   std::string const & layout);
101         ///
102         void setLayout(std::string const & layout);
103
104         /// Increase or decrease the nesting depth of the selected paragraph(s)
105         void changeDepth(bv_funcs::DEPTH_CHANGE type);
106
107         /// Returns whether something would be changed by changeDepth
108         bool changeDepthAllowed(bv_funcs::DEPTH_CHANGE type);
109
110         /// get the depth at current cursor position
111         int getDepth() const;
112
113         /** set font over selection and make a total rebreak of those
114           paragraphs.
115           toggleall defaults to false.
116           */
117         void setFont(LyXFont const &, bool toggleall = false);
118
119         /// rebreaks all paragaphs between the given pars.
120         void redoParagraphs(ParagraphList::iterator begin,
121                             ParagraphList::iterator end);
122         /// rebreaks the given par
123         void redoParagraph(ParagraphList::iterator pit);
124
125         /// rebreaks the cursor par
126         void redoParagraph();
127
128         ///
129         void toggleFree(LyXFont const &, bool toggleall = false);
130
131         ///
132         std::string getStringToIndex();
133
134         /** insert a character, moves all the following breaks in the
135           same Paragraph one to the right and make a little rebreak
136           */
137         void insertChar(char c);
138         ///
139         void insertInset(InsetOld * inset);
140
141         /// a full rebreak of the whole text
142         void fullRebreak();
143         /// compute text metrics
144         void metrics(MetricsInfo & mi, Dimension & dim);
145         /// draw text (only used for insets)
146         void draw(PainterInfo & pi, int x, int y) const;
147
148         /// try to handle that request
149         DispatchResult dispatch(FuncRequest const & cmd);
150
151         BufferView * bv();
152
153         BufferView * bv() const;
154
155         friend class LyXScreen;
156
157         /// returns an iterator pointing to a cursor paragraph
158         ParagraphList::iterator getPar(CursorSlice const & cursor) const;
159         ///
160         ParagraphList::iterator getPar(lyx::paroffset_type par) const;
161         ///
162         int parOffset(ParagraphList::iterator pit) const;
163         /// convenience
164         ParagraphList::iterator cursorPar() const;
165         ///
166         RowList::iterator cursorRow() const;
167
168         /** returns an iterator pointing to the row near the specified
169           * y-coordinate (relative to the whole text). y is set to the
170           * real beginning of this row
171           */
172         RowList::iterator getRowNearY(int y,
173                 ParagraphList::iterator & pit) const;
174
175         /** returns the column near the specified x-coordinate of the row
176          x is set to the real beginning of this column
177          */
178         lyx::pos_type getColumnNearX(ParagraphList::iterator pit,
179                 Row const & row, int & x, bool & boundary) const;
180
181         /// select the word we need depending on word_location
182         void getWord(CursorSlice & from, CursorSlice & to, lyx::word_location const);
183         /// just selects the word the cursor is in
184         void selectWord(lyx::word_location loc);
185         /// returns the inset at cursor (if it exists), 0 otherwise
186         InsetOld * getInset() const;
187
188         /// accept selected change
189         void acceptChange();
190
191         /// reject selected change
192         void rejectChange();
193
194         ///
195         void setCursor(ParagraphList::iterator pit, lyx::pos_type pos);
196         /// returns true if par was empty and was removed
197         bool setCursor(lyx::paroffset_type par, lyx::pos_type pos,
198                        bool setfont = true, bool boundary = false);
199         ///
200         void setCursor(CursorSlice &, lyx::paroffset_type par,
201                        lyx::pos_type pos, bool boundary = false);
202         ///
203         void setCursorIntern(lyx::paroffset_type par, lyx::pos_type pos,
204                              bool setfont = true, bool boundary = false);
205         ///
206         void setCurrentFont();
207
208         ///
209         void recUndo(lyx::paroffset_type first, lyx::paroffset_type last) const;
210         ///
211         void recUndo(lyx::paroffset_type first) const;
212         ///
213         void setCursorFromCoordinates(int x, int y);
214         ///
215         void setCursorFromCoordinates(CursorSlice &, int x, int y);
216         ///
217         void cursorUp(bool selecting = false);
218         ///
219         void cursorDown(bool selecting = false);
220         ///
221         bool cursorLeft(bool internal = true);
222         ///
223         bool cursorRight(bool internal = true);
224         ///
225         void cursorLeftOneWord();
226         ///
227         void cursorRightOneWord();
228         ///
229         void cursorUpParagraph();
230         ///
231         void cursorDownParagraph();
232         ///
233         void cursorHome();
234         ///
235         void cursorEnd();
236         ///
237         void cursorPrevious();
238         ///
239         void cursorNext();
240         ///
241         void cursorTop();
242         ///
243         void cursorBottom();
244         ///
245         void Delete();
246         ///
247         void backspace();
248         ///
249         bool selectWordWhenUnderCursor(lyx::word_location);
250         ///
251         enum TextCase {
252                 ///
253                 text_lowercase = 0,
254                 ///
255                 text_capitalization = 1,
256                 ///
257                 text_uppercase = 2
258         };
259         /// Change the case of the word at cursor position.
260         void changeCase(TextCase action);
261
262         /// returns success
263         bool toggleInset();
264         ///
265         void cutSelection(bool doclear = true, bool realcut = true);
266         ///
267         void copySelection();
268         ///
269         void pasteSelection(size_t sel_index = 0);
270
271         /** the DTP switches for paragraphs. LyX will store the top settings
272          always in the first physical paragraph, the bottom settings in the
273          last. When a paragraph is broken, the top settings rest, the bottom
274          settings are given to the new one.
275          */
276         void setParagraph(
277                           Spacing const & spacing,
278                           LyXAlignment align,
279                           std::string const & labelwidthstring,
280                           bool noindent);
281
282         /* these things are for search and replace */
283
284         /**
285          * Sets the selection from the current cursor position to length
286          * characters to the right. No safety checks.
287          */
288         void setSelectionRange(lyx::pos_type length);
289
290         /** simple replacing. The font of the first selected character
291           is used
292           */
293         void replaceSelectionWithString(std::string const & str);
294
295         /// needed to insert the selection
296         void insertStringAsLines(std::string const & str);
297         /// needed to insert the selection
298         void insertStringAsParagraphs(std::string const & str);
299
300         /// Find next inset of some specified type.
301         bool gotoNextInset(std::vector<InsetOld::Code> const & codes,
302                            std::string const & contents = std::string());
303         ///
304         void gotoInset(std::vector<InsetOld::Code> const & codes,
305                        bool same_content);
306         ///
307         void gotoInset(InsetOld::Code code, bool same_content);
308
309         /// current max text width
310         int textWidth() const;
311
312         /// updates all counters
313         void updateCounters();
314         /// Returns an inset if inset was hit, or 0 if not.
315         InsetOld * checkInsetHit(int x, int y);
316
317         ///
318         int singleWidth(ParagraphList::iterator pit, lyx::pos_type pos) const;
319         ///
320         int singleWidth(ParagraphList::iterator pit,
321                 lyx::pos_type pos, char c, LyXFont const & Font) const;
322
323         /// return the color of the canvas
324         LColor_color backgroundColor() const;
325
326         /**
327          * Returns the left beginning of the text.
328          * This information cannot be taken from the layout object, because
329          * in LaTeX the beginning of the text fits in some cases
330          * (for example sections) exactly the label-width.
331          */
332         int leftMargin(ParagraphList::iterator pit, lyx::pos_type pos) const;
333         int leftMargin(ParagraphList::iterator pit) const;
334         ///
335         int rightMargin(Paragraph const & par) const;
336
337         /** this calculates the specified parameters. needed when setting
338          * the cursor and when creating a visible row */
339         void prepareToPrint(ParagraphList::iterator pit, Row & row) const;
340
341         //
342         // special owner functions
343         ///
344         ParagraphList & paragraphs() const;
345
346         /// return true if this is owned by an inset.
347         bool isInInset() const;
348
349         ///
350         ParagraphList::iterator firstPar() const;
351         ///
352         ParagraphList::iterator lastPar() const;
353         ///
354         ParagraphList::iterator endPar() const;
355         
356         /// return first row of text
357         RowList::iterator firstRow() const;
358         /// return last row of text
359         RowList::iterator lastRow() const;
360         /// return row "behind" last row of text
361         RowList::iterator endRow() const;
362         /// return next row crossing paragraph boundaries
363         void nextRow(ParagraphList::iterator & pit,
364                 RowList::iterator & rit) const;
365         /// return previous row crossing paragraph boundaries
366         void previousRow(ParagraphList::iterator & pit,
367                 RowList::iterator & rit) const;
368
369         /// is this row the last in the text?
370         bool isLastRow(ParagraphList::iterator pit, Row const & row) const;
371         /// is this row the first in the text?
372         bool isFirstRow(ParagraphList::iterator pit, Row const & row) const;
373
374         ///
375         std::string selectionAsString(Buffer const & buffer, bool label) const;
376         ///
377         double spacing(Paragraph const &) const;
378         ///
379         void cursorLeftOneWord(CursorSlice &);
380         ///
381         void cursorRightOneWord(CursorSlice &);
382
383         ///
384         DispatchResult moveRight();
385         ///
386         DispatchResult moveLeft();
387         ///
388         DispatchResult moveRightIntern(bool front,
389                 bool activate_inset, bool selecting);
390         ///
391         DispatchResult moveLeftIntern(bool front,
392                 bool activate_inset, bool selecting);
393         ///
394         DispatchResult moveUp();
395         ///
396         DispatchResult moveDown();
397         ///
398         bool checkAndActivateInset(bool front);
399
400         ///
401         void write(Buffer const & buf, std::ostream & os) const;
402         /// returns whether we've seen our usual 'end' marker
403         bool read(Buffer const & buf, LyXLex & lex);
404
405         ///
406         int ascent() const;
407         ///
408         int descent() const;
409         ///
410         int cursorX() const;
411         ///
412         int cursorY() const;
413         ///
414         int cursorX(CursorSlice const & cursor) const;
415         ///
416         int cursorY(CursorSlice const & cursor) const;
417
418         /// the topmost cursor slice
419         CursorSlice & cursor();
420         /// the topmost cursor slice
421         CursorSlice const & cursor() const;
422         /// access to the selection anchor
423         CursorSlice & anchor();
424         /// access to the selection anchor
425         CursorSlice const & anchor() const;
426
427         ///
428         void setSelection();
429         ///
430         void clearSelection();
431         ///
432         CursorSlice const & selStart() const;
433         ///
434         CursorSlice const & selEnd() const;
435         ///
436         CursorSlice & selStart();
437         ///
438         CursorSlice & selEnd();
439
440
441 public:
442 /** The cursor.
443         Later this variable has to be removed. There should be no internal
444         cursor in a text (and thus not in a buffer). By keeping this it is
445         (I think) impossible to have several views with the same buffer, but
446         the cursor placed at different places.
447         [later]
448         Since the LyXText now has been moved from Buffer to BufferView
449         it should not be absolutely needed to move the cursor...
450         [even later]
451         Nevertheless, it should still be moved, in order to keep classes
452         and interdependencies small.
453         */
454         // the other end of the selection
455         CursorSlice anchor_;
456         //
457         Selection selection;
458
459         ///
460         int height;
461         ///
462         unsigned int width;
463         ///
464         int textwidth_;
465         /// the current font settings
466         LyXFont current_font;
467         /// the current font
468         LyXFont real_current_font;
469         /// our buffer's default layout font
470         LyXFont defaultfont_;
471         ///
472         int background_color_;
473
474         /// only the top-level LyXText has this non-zero
475         BufferView * bv_owner;
476
477         ///
478         mutable Bidi bidi;
479         ///
480         bool in_inset_;
481         ///
482         ParagraphList paragraphs_;
483
484         /// absolute document pixel coordinates of this LyXText
485         mutable int xo_;
486         mutable int yo_;
487
488         /// our 'outermost' Font
489         LyXFont font_;
490
491
492 private:
493         /// return past-the-last paragraph influenced by a layout
494         /// change on pit
495         ParagraphList::iterator undoSpan(ParagraphList::iterator pit);
496         
497         /// rebreaks the given par
498         void redoParagraphInternal(ParagraphList::iterator pit);
499         /// used in setlayout
500         void makeFontEntriesLayoutSpecific(BufferParams const &, Paragraph & par);
501
502         /// Calculate and set the height of the row
503         void setHeightOfRow(ParagraphList::iterator, Row & row);
504
505         // fix the cursor `cur' after a characters has been deleted at `where'
506         // position. Called by deleteEmptyParagraphMechanism
507         void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where);
508
509         /// delete double space (false) or empty paragraphs (true) around old_cursor
510         bool deleteEmptyParagraphMechanism(CursorSlice const & old_cursor);
511
512         ///
513         void setCounter(Buffer const &, ParagraphList::iterator pit);
514         ///
515         void deleteWordForward();
516         ///
517         void deleteWordBackward();
518         ///
519         void deleteLineForward();
520
521         /// sets row.end to the pos value *after* which a row should break.
522         /// for example, the pos after which isNewLine(pos) == true
523         void rowBreakPoint(ParagraphList::iterator pit, Row & row) const;
524
525         /// sets row.witdh to the minimum space a row needs on the screen in pixel
526         void fill(ParagraphList::iterator pit, Row & row, int workwidth) const;
527
528         /**
529          * returns the minimum space a manual label needs on the
530          * screen in pixels
531          */
532         int labelFill(ParagraphList::iterator pit, Row const & row) const;
533
534         /// FIXME
535         int labelEnd(ParagraphList::iterator pit) const;
536
537         ///
538         void charInserted();
539         /// set 'number' font property
540         void number();
541         /// is the cursor paragraph right-to-left?
542         bool rtl() const;
543 };
544
545 /// return the default height of a row in pixels, considering font zoom
546 extern int defaultRowHeight();
547
548 ///
549 std::string expandLabel(LyXTextClass const & textclass,
550                 LyXLayout_ptr const & layout, bool appendix);
551
552 #endif // LYXTEXT_H