]> git.lyx.org Git - lyx.git/blob - src/lyxtext.h
e652eb8efc6e7cc94a92eb034419115ee7b36ac5
[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         /** Find the word under \c from in the relative location
182          *  defined by \c word_location.
183          *  @param from return here the start of the word
184          *  @param to return here the end of the word
185          */
186         void getWord(CursorSlice & from, CursorSlice & to, lyx::word_location const);
187         /// just selects the word the cursor is in
188         void selectWord(lyx::word_location loc);
189         /// returns the inset at cursor (if it exists), 0 otherwise
190         InsetOld * getInset() const;
191
192         /// accept selected change
193         void acceptChange();
194
195         /// reject selected change
196         void rejectChange();
197
198         ///
199         void setCursor(ParagraphList::iterator pit, lyx::pos_type pos);
200         /// returns true if par was empty and was removed
201         bool setCursor(lyx::paroffset_type par, lyx::pos_type pos,
202                        bool setfont = true, bool boundary = false);
203         ///
204         void setCursor(CursorSlice &, lyx::paroffset_type par,
205                        lyx::pos_type pos, bool boundary = false);
206         ///
207         void setCursorIntern(lyx::paroffset_type par, lyx::pos_type pos,
208                              bool setfont = true, bool boundary = false);
209         ///
210         void setCurrentFont();
211
212         ///
213         void recUndo(lyx::paroffset_type first, lyx::paroffset_type last) const;
214         ///
215         void recUndo(lyx::paroffset_type first) const;
216         ///
217         void setCursorFromCoordinates(int x, int y);
218         ///
219         void setCursorFromCoordinates(CursorSlice &, int x, int y);
220         ///
221         void cursorUp(bool selecting = false);
222         ///
223         void cursorDown(bool selecting = false);
224         ///
225         bool cursorLeft(bool internal = true);
226         ///
227         bool cursorRight(bool internal = true);
228         ///
229         void cursorLeftOneWord();
230         ///
231         void cursorRightOneWord();
232         ///
233         void cursorUpParagraph();
234         ///
235         void cursorDownParagraph();
236         ///
237         void cursorHome();
238         ///
239         void cursorEnd();
240         ///
241         void cursorPrevious();
242         ///
243         void cursorNext();
244         ///
245         void cursorTop();
246         ///
247         void cursorBottom();
248         ///
249         void Delete();
250         ///
251         void backspace();
252         ///
253         bool selectWordWhenUnderCursor(lyx::word_location);
254         ///
255         enum TextCase {
256                 ///
257                 text_lowercase = 0,
258                 ///
259                 text_capitalization = 1,
260                 ///
261                 text_uppercase = 2
262         };
263         /// Change the case of the word at cursor position.
264         void changeCase(TextCase action);
265
266         /// returns success
267         bool toggleInset();
268         ///
269         void cutSelection(bool doclear = true, bool realcut = true);
270         ///
271         void copySelection();
272         ///
273         void pasteSelection(size_t sel_index = 0);
274
275         /** the DTP switches for paragraphs. LyX will store the top settings
276          always in the first physical paragraph, the bottom settings in the
277          last. When a paragraph is broken, the top settings rest, the bottom
278          settings are given to the new one.
279          */
280         void setParagraph(
281                           Spacing const & spacing,
282                           LyXAlignment align,
283                           std::string const & labelwidthstring,
284                           bool noindent);
285
286         /* these things are for search and replace */
287
288         /**
289          * Sets the selection from the current cursor position to length
290          * characters to the right. No safety checks.
291          */
292         void setSelectionRange(lyx::pos_type length);
293
294         /** simple replacing. The font of the first selected character
295           is used
296           */
297         void replaceSelectionWithString(std::string const & str);
298
299         /// needed to insert the selection
300         void insertStringAsLines(std::string const & str);
301         /// needed to insert the selection
302         void insertStringAsParagraphs(std::string const & str);
303
304         /// Find next inset of some specified type.
305         bool gotoNextInset(std::vector<InsetOld::Code> const & codes,
306                            std::string const & contents = std::string());
307         ///
308         void gotoInset(std::vector<InsetOld::Code> const & codes,
309                        bool same_content);
310         ///
311         void gotoInset(InsetOld::Code code, bool same_content);
312
313         /// current max text width
314         int textWidth() const;
315
316         /// updates all counters
317         void updateCounters();
318         /// Returns an inset if inset was hit, or 0 if not.
319         InsetOld * checkInsetHit(int x, int y);
320
321         ///
322         int singleWidth(ParagraphList::iterator pit, lyx::pos_type pos) const;
323         ///
324         int singleWidth(ParagraphList::iterator pit,
325                 lyx::pos_type pos, char c, LyXFont const & Font) const;
326
327         /// return the color of the canvas
328         LColor_color backgroundColor() const;
329
330         /**
331          * Returns the left beginning of the text.
332          * This information cannot be taken from the layout object, because
333          * in LaTeX the beginning of the text fits in some cases
334          * (for example sections) exactly the label-width.
335          */
336         int leftMargin(ParagraphList::iterator pit, lyx::pos_type pos) const;
337         int leftMargin(ParagraphList::iterator pit) const;
338         ///
339         int rightMargin(Paragraph const & par) const;
340
341         /** this calculates the specified parameters. needed when setting
342          * the cursor and when creating a visible row */
343         void prepareToPrint(ParagraphList::iterator pit, Row & row) const;
344
345         //
346         // special owner functions
347         ///
348         ParagraphList & paragraphs() const;
349
350         /// return true if this is owned by an inset.
351         bool isInInset() const;
352
353         ///
354         ParagraphList::iterator firstPar() const;
355         ///
356         ParagraphList::iterator lastPar() const;
357         ///
358         ParagraphList::iterator endPar() const;
359         
360         /// return first row of text
361         RowList::iterator firstRow() const;
362         /// return last row of text
363         RowList::iterator lastRow() const;
364         /// return row "behind" last row of text
365         RowList::iterator endRow() const;
366         /// return next row crossing paragraph boundaries
367         void nextRow(ParagraphList::iterator & pit,
368                 RowList::iterator & rit) const;
369         /// return previous row crossing paragraph boundaries
370         void previousRow(ParagraphList::iterator & pit,
371                 RowList::iterator & rit) const;
372
373         /// is this row the last in the text?
374         bool isLastRow(ParagraphList::iterator pit, Row const & row) const;
375         /// is this row the first in the text?
376         bool isFirstRow(ParagraphList::iterator pit, Row const & row) const;
377
378         ///
379         std::string selectionAsString(Buffer const & buffer, bool label) const;
380         ///
381         double spacing(Paragraph const &) const;
382         ///
383         void cursorLeftOneWord(CursorSlice &);
384         ///
385         void cursorRightOneWord(CursorSlice &);
386
387         ///
388         DispatchResult moveRight();
389         ///
390         DispatchResult moveLeft();
391         ///
392         DispatchResult moveRightIntern(bool front,
393                 bool activate_inset, bool selecting);
394         ///
395         DispatchResult moveLeftIntern(bool front,
396                 bool activate_inset, bool selecting);
397         ///
398         DispatchResult moveUp();
399         ///
400         DispatchResult moveDown();
401         ///
402         bool checkAndActivateInset(bool front);
403
404         ///
405         void write(Buffer const & buf, std::ostream & os) const;
406         /// returns whether we've seen our usual 'end' marker
407         bool read(Buffer const & buf, LyXLex & lex);
408
409         ///
410         int ascent() const;
411         ///
412         int descent() const;
413         ///
414         int cursorX() const;
415         ///
416         int cursorY() const;
417         ///
418         int cursorX(CursorSlice const & cursor) const;
419         ///
420         int cursorY(CursorSlice const & cursor) const;
421
422         /// the topmost cursor slice
423         CursorSlice & cursor();
424         /// the topmost cursor slice
425         CursorSlice const & cursor() const;
426         /// access to the selection anchor
427         CursorSlice & anchor();
428         /// access to the selection anchor
429         CursorSlice const & anchor() const;
430
431         ///
432         void setSelection();
433         ///
434         void clearSelection();
435         ///
436         CursorSlice const & selStart() const;
437         ///
438         CursorSlice const & selEnd() const;
439         ///
440         CursorSlice & selStart();
441         ///
442         CursorSlice & selEnd();
443
444
445 public:
446 /** The cursor.
447         Later this variable has to be removed. There should be no internal
448         cursor in a text (and thus not in a buffer). By keeping this it is
449         (I think) impossible to have several views with the same buffer, but
450         the cursor placed at different places.
451         [later]
452         Since the LyXText now has been moved from Buffer to BufferView
453         it should not be absolutely needed to move the cursor...
454         [even later]
455         Nevertheless, it should still be moved, in order to keep classes
456         and interdependencies small.
457         */
458         // the other end of the selection
459         CursorSlice anchor_;
460         //
461         Selection selection;
462
463         ///
464         int height;
465         ///
466         unsigned int width;
467         ///
468         int textwidth_;
469         /// the current font settings
470         LyXFont current_font;
471         /// the current font
472         LyXFont real_current_font;
473         /// our buffer's default layout font
474         LyXFont defaultfont_;
475         ///
476         int background_color_;
477
478         /// only the top-level LyXText has this non-zero
479         BufferView * bv_owner;
480
481         ///
482         mutable Bidi bidi;
483         ///
484         bool in_inset_;
485         ///
486         ParagraphList paragraphs_;
487
488         /// absolute document pixel coordinates of this LyXText
489         mutable int xo_;
490         mutable int yo_;
491
492         /// our 'outermost' Font
493         LyXFont font_;
494
495
496 private:
497         /// return past-the-last paragraph influenced by a layout
498         /// change on pit
499         ParagraphList::iterator undoSpan(ParagraphList::iterator pit);
500         
501         /// rebreaks the given par
502         void redoParagraphInternal(ParagraphList::iterator pit);
503         /// used in setlayout
504         void makeFontEntriesLayoutSpecific(BufferParams const &, Paragraph & par);
505
506         /// Calculate and set the height of the row
507         void setHeightOfRow(ParagraphList::iterator, Row & row);
508
509         // fix the cursor `cur' after a characters has been deleted at `where'
510         // position. Called by deleteEmptyParagraphMechanism
511         void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where);
512
513         /// delete double space (false) or empty paragraphs (true) around old_cursor
514         bool deleteEmptyParagraphMechanism(CursorSlice const & old_cursor);
515
516         ///
517         void setCounter(Buffer const &, ParagraphList::iterator pit);
518         ///
519         void deleteWordForward();
520         ///
521         void deleteWordBackward();
522         ///
523         void deleteLineForward();
524
525         /// sets row.end to the pos value *after* which a row should break.
526         /// for example, the pos after which isNewLine(pos) == true
527         void rowBreakPoint(ParagraphList::iterator pit, Row & row) const;
528
529         /// sets row.witdh to the minimum space a row needs on the screen in pixel
530         void fill(ParagraphList::iterator pit, Row & row, int workwidth) const;
531
532         /**
533          * returns the minimum space a manual label needs on the
534          * screen in pixels
535          */
536         int labelFill(ParagraphList::iterator pit, Row const & row) const;
537
538         /// FIXME
539         int labelEnd(ParagraphList::iterator pit) const;
540
541         ///
542         void charInserted();
543         /// set 'number' font property
544         void number();
545         /// is the cursor paragraph right-to-left?
546         bool rtl() const;
547 };
548
549 /// return the default height of a row in pixels, considering font zoom
550 extern int defaultRowHeight();
551
552 ///
553 std::string expandLabel(LyXTextClass const & textclass,
554                 LyXLayout_ptr const & layout, bool appendix);
555
556 #endif // LYXTEXT_H