2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1995 Matthias Ettrich
8 * Copyright 1995-2001 The LyX Team.
10 * ====================================================== */
21 #include "lyxcursor.h"
22 #include "paragraph.h"
34 This class holds the mapping between buffer paragraphs and screen rows.
45 NEED_VERY_LITTLE_REFRESH,
51 LyXText(BufferView *);
58 void init(BufferView *);
60 mutable int number_of_rows;
64 mutable unsigned int width;
65 /// the current font settings
66 mutable LyXFont current_font;
68 mutable LyXFont real_current_font;
69 /// first visible pixel-row is set from LyXScreen!!!
70 // unsigned is wrong here for text-insets!
73 BufferView * bv_owner;
75 InsetText * inset_owner;
77 UpdatableInset * the_locking_inset;
80 int getRealCursorX(BufferView *) const;
82 LyXFont const getFont(Buffer const *, Paragraph * par,
83 Paragraph::size_type pos) const;
85 void setCharFont(Buffer const *, Paragraph * par,
86 Paragraph::size_type pos, LyXFont const & font);
87 void setCharFont(BufferView *, Paragraph * par,
88 Paragraph::size_type pos,
89 LyXFont const & font, bool toggleall);
90 /// returns a pointer to the very first Paragraph
91 Paragraph * firstParagraph() const;
93 /// what you expect when pressing <enter> at cursor position
94 void breakParagraph(BufferView *, char keep_layout = 0);
96 /** set layout over selection and make a total rebreak of
99 Paragraph * setLayout(BufferView *, LyXCursor & actual_cursor,
100 LyXCursor & selection_start,
101 LyXCursor & selection_end,
102 LyXTextClass::size_type layout);
103 void setLayout(BufferView *, LyXTextClass::size_type layout);
105 /// used in setlayout
106 void makeFontEntriesLayoutSpecific(Buffer const *, Paragraph * par);
108 /** increment depth over selection and make a total rebreak of those
111 void incDepth(BufferView *);
113 /** decrement depth over selection and make a total rebreak of those
115 void decDepth(BufferView *);
117 /** Get the depth at current cursor position
119 int getDepth() const { return cursor.par()->getDepth(); }
121 /** set font over selection and make a total rebreak of those
123 toggleall defaults to false.
125 void setFont(BufferView *, LyXFont const &, bool toggleall = false);
127 /** deletes and inserts again all paragaphs between the cursor
128 and the specified par. The Cursor is needed to set the refreshing
130 This function is needed after SetLayout and SetFont etc.
132 void redoParagraphs(BufferView *, LyXCursor const & cursor,
133 Paragraph const * end_par) const;
135 void redoParagraph(BufferView *) const;
138 void toggleFree(BufferView *, LyXFont const &, bool toggleall = false);
140 /** recalculates the heights of all previous rows of the
141 specified paragraph. needed, if the last characters font
144 void redoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
146 /** forces the redrawing of a paragraph. Needed when manipulating a
149 void redoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
151 /** insert a character, moves all the following breaks in the
152 same Paragraph one to the right and make a little rebreak
154 void insertChar(BufferView *, char c);
156 void insertInset(BufferView *, Inset * inset);
158 /** Completes the insertion with a full rebreak.
159 Returns true if something was broken. */
160 bool fullRebreak(BufferView *);
163 Row * need_break_row;
165 mutable int refresh_y;
173 mutable Row * refresh_row;
177 /** wether the screen needs a refresh,
178 starting with refresh_y
180 mutable text_status status;
182 /** returns a pointer to the row near the specified y-coordinate
183 (relative to the whole text). y is set to the real beginning
186 Row * getRowNearY(int & y) const;
188 /** returns the column near the specified x-coordinate of the row
189 x is set to the real beginning of this column
191 int getColumnNearX(BufferView *, Row * row,
192 int & x, bool & boundary) const;
194 /** returns a pointer to a specified row. y is set to the beginning
197 Row * getRow(Paragraph * par,
198 Paragraph::size_type pos, int & y) const;
200 /** returns the height of a default row, needed for scrollbar
202 int defaultHeight() const;
205 Later this variable has to be removed. There should be now internal
206 cursor in a text (and thus not in a buffer). By keeping this it is
207 (I think) impossible to have several views with the same buffer, but
208 the cursor placed at different places.
210 Since the LyXText now has been moved from Buffer to BufferView
211 it should not be absolutely needed to move the cursor...
213 mutable LyXCursor cursor;
216 /* the selection cursor */
218 mutable bool selection;
220 mutable bool mark_set;
223 mutable LyXCursor sel_cursor;
225 mutable LyXCursor sel_start_cursor;
227 mutable LyXCursor sel_end_cursor;
229 /** The structrue that keeps track of the selections set. */
247 bool set_; // former selection
248 bool mark_; // former mark_set
251 mutable Selection selection;
253 /// needed for the toggling
254 LyXCursor last_sel_cursor;
256 LyXCursor toggle_cursor;
258 LyXCursor toggle_end_cursor;
260 /// need the selection cursor:
261 void setSelection(BufferView *);
263 void clearSelection(BufferView *) const;
265 string const selectionAsString(Buffer const *) const;
267 /// just selects the word the cursor is in
268 void selectWord(BufferView *);
270 /** 'selects" the next word, where the cursor is not in
271 and returns this word as string. THe cursor will be moved
272 to the beginning of this word.
273 With SelectSelectedWord can this be highlighted really
275 string const selectNextWord(BufferView *, float & value) const;
277 void selectSelectedWord(BufferView *);
279 void setCursor(BufferView *, Paragraph * par,
280 Paragraph::size_type pos,
282 bool boundary = false) const;
284 void setCursor(BufferView *, LyXCursor &, Paragraph * par,
285 Paragraph::size_type pos,
286 bool boundary = false) const;
288 void setCursorIntern(BufferView *, Paragraph * par,
289 Paragraph::size_type pos,
291 bool boundary = false) const;
293 void setCurrentFont(BufferView *) const;
296 bool isBoundary(Buffer const *, Paragraph * par,
297 Paragraph::size_type pos) const;
299 bool isBoundary(Buffer const *, Paragraph * par,
300 Paragraph::size_type pos,
301 LyXFont const & font) const;
304 void setCursorFromCoordinates(BufferView *, int x, int y) const;
306 void setCursorFromCoordinates(BufferView *, LyXCursor &,
309 void cursorUp(BufferView *) const;
311 void cursorDown(BufferView *) const;
313 void cursorLeft(BufferView *, bool internal = true) const;
315 void cursorRight(BufferView *, bool internal = true) const;
317 void cursorLeftOneWord(BufferView *) const;
319 void cursorRightOneWord(BufferView *) const;
321 void cursorUpParagraph(BufferView *) const;
323 void cursorDownParagraph(BufferView *) const;
325 void cursorHome(BufferView *) const;
327 void cursorEnd(BufferView *) const;
329 void cursorTab(BufferView *) const;
331 void cursorTop(BufferView *) const;
333 void cursorBottom(BufferView *) const;
335 void Delete(BufferView *);
337 void backspace(BufferView *);
339 void deleteWordForward(BufferView *);
341 void deleteWordBackward(BufferView *);
343 void deleteLineForward(BufferView *);
345 bool selectWordWhenUnderCursor(BufferView *);
351 text_capitalization = 1,
355 /// Change the case of the word at cursor position.
356 void changeWordCase(BufferView *, TextCase action);
358 void transposeChars(BufferView const &);
360 /** returns a printed row in a pixmap. The y value is needed to
361 decide, wether it is selected text or not. This is a strange
364 void getVisibleRow(BufferView *, int y_offset, int x_offset,
365 Row * row_ptr, int y, bool cleared=false);
368 void cutSelection(BufferView *, bool = true);
370 void copySelection(BufferView *);
372 void pasteSelection(BufferView *);
374 void copyEnvironmentType();
376 void pasteEnvironmentType(BufferView *);
378 void insertFootnote();
380 void insertMarginpar();
384 void insertTabular();
386 /** the DTP switches for paragraphs. LyX will store the top settings
387 always in the first physical paragraph, the bottom settings in the
388 last. When a paragraph is broken, the top settings rest, the bottom
389 settings are given to the new one. So I can make shure, they do not
390 duplicate themself (and you cannnot make dirty things with them! )
392 void setParagraph(BufferView *,
393 bool line_top, bool line_bottom,
394 bool pagebreak_top, bool pagebreak_bottom,
395 VSpace const & space_top,
396 VSpace const & space_bottom,
398 string labelwidthstring,
401 /* these things are for search and replace */
403 /** sets the selection over the number of characters of string,
406 void setSelectionOverString(BufferView *, string const & str);
408 /** simple replacing. The font of the first selected character
411 void replaceSelectionWithString(BufferView *, string const & str);
413 /// needed to insert the selection
414 void insertStringAsLines(BufferView *, string const & str);
415 /// needed to insert the selection
416 void insertStringAsParagraphs(BufferView *, string const & str);
418 /// Find next inset of some specified type.
419 bool gotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
420 string const & contents = string()) const;
423 /* for the greater insets */
425 /// returns false if inset wasn't found
426 bool updateInset(BufferView *, Inset *);
428 void checkParagraph(BufferView *, Paragraph * par,
429 Paragraph::size_type pos);
431 int numberOfCell(Paragraph * par,
432 Paragraph::size_type pos) const;
434 Paragraph * getParFromID(int id);
437 /// returns false if no undo possible
438 bool textUndo(BufferView *);
439 /// returns false if no redo possible
440 bool textRedo(BufferView *);
441 /// used by TextUndo/TextRedo
442 bool textHandleUndo(BufferView *, Undo * undo);
443 /// makes sure the next operation will be stored
445 /// this is dangerous and for internal use only
447 /// this is dangerous and for internal use only
449 /// the flag used by FinishUndo();
450 mutable bool undo_finished;
454 void setUndo(Buffer *, Undo::undo_kind kind,
455 Paragraph const * before,
456 Paragraph const * end) const;
458 void setRedo(Buffer *, Undo::undo_kind kind,
459 Paragraph const * before,
460 Paragraph const * end);
462 Undo * createUndo(Buffer *, Undo::undo_kind kind,
463 Paragraph const * before,
464 Paragraph const * end) const;
465 /// for external use in lyx_cb.C
466 void setCursorParUndo(Buffer *);
468 void removeTableRow(LyXCursor & cursor) const;
470 bool isEmptyTableCell() const;
472 void toggleAppendix(BufferView *);
474 int workWidth(BufferView *) const;
476 void computeBidiTables(Buffer const *, Row * row) const;
478 /// Maps positions in the visual string to positions in logical string.
480 Paragraph::size_type log2vis(Paragraph::size_type pos) const {
481 if (bidi_start == -1)
484 return log2vis_list[pos-bidi_start];
487 /// Maps positions in the logical string to positions in visual string.
489 Paragraph::size_type vis2log(Paragraph::size_type pos) const {
490 if (bidi_start == -1)
493 return vis2log_list[pos-bidi_start];
497 Paragraph::size_type bidi_level(Paragraph::size_type pos) const {
498 if (bidi_start == -1)
501 return bidi_levels[pos-bidi_start];
505 bool bidi_InRange(Paragraph::size_type pos) const {
506 return bidi_start == -1 ||
507 (bidi_start <= pos && pos <= bidi_end);
513 mutable Row * firstrow;
515 mutable Row * lastrow;
517 /** Copybuffer for copy environment type.
518 Asger has learned that this should be a buffer-property instead
519 Lgb has learned that 'char' is a lousy type for non-characters
521 LyXTextClass::size_type copylayouttype;
523 /** inserts a new row behind the specified row, increments
524 the touched counters */
525 void insertRow(Row * row, Paragraph * par,
526 Paragraph::size_type pos) const;
527 /** removes the row and reset the touched counters */
528 void removeRow(Row * row) const;
530 /** remove all following rows of the paragraph of the specified row. */
531 void removeParagraph(Row * row) const;
533 /** insert the specified paragraph behind the specified row */
534 void insertParagraph(BufferView *,
535 Paragraph * par, Row * row) const;
537 /** appends the implizit specified paragraph behind the specified row,
538 * start at the implizit given position */
539 void appendParagraph(BufferView *, Row * row) const;
542 void breakAgain(BufferView *, Row * row) const;
544 void breakAgainOneRow(BufferView *, Row * row);
545 /// Calculate and set the height of the row
546 void setHeightOfRow(BufferView *, Row * row_ptr) const;
548 /** this calculates the specified parameters. needed when setting
549 * the cursor and when creating a visible row */
550 void prepareToPrint(BufferView *, Row * row, float & x,
551 float & fill_separator,
553 float & fill_label_hfill,
554 bool bidi = true) const;
557 void deleteEmptyParagraphMechanism(BufferView *,
558 LyXCursor const & old_cursor) const;
560 /** Updates all counters starting BEHIND the row. Changed paragraphs
561 * with a dynamic left margin will be rebroken. */
562 void updateCounters(BufferView *, Row * row) const;
564 void setCounter(Buffer const *, Paragraph * par) const;
567 * some low level functions
571 int singleWidth(BufferView *, Paragraph * par,
572 Paragraph::size_type pos) const;
574 int singleWidth(BufferView *, Paragraph * par,
575 Paragraph::size_type pos, char c) const;
577 void draw(BufferView *, Row const * row,
578 Paragraph::size_type & pos,
579 int offset, float & x, bool cleared);
581 /// get the next breakpoint in a given paragraph
582 Paragraph::size_type nextBreakPoint(BufferView *, Row const * row,
584 /// returns the minimum space a row needs on the screen in pixel
585 int fill(BufferView *, Row * row, int workwidth) const;
587 /** returns the minimum space a manual label needs on the
589 int labelFill(BufferView *, Row const * row) const;
593 beginningOfMainBody(Buffer const *, Paragraph const * par) const;
595 /** Returns the left beginning of the text.
596 This information cannot be taken from the layouts-objekt, because
597 in LaTeX the beginning of the text fits in some cases
598 (for example sections) exactly the label-width.
600 int leftMargin(BufferView *, Row const * row) const;
602 int rightMargin(Buffer const *, Row const * row) const;
604 int labelEnd (BufferView *, Row const * row) const;
606 /** returns the number of separators in the specified row.
607 The separator on the very last column doesnt count
609 int numberOfSeparators(Buffer const *, Row const * row) const;
611 /** returns the number of hfills in the specified row. The
612 LyX-Hfill is a LaTeX \hfill so that the hfills at the
613 beginning and at the end were ignored. This is {\em MUCH}
614 more usefull than not to ignore!
616 int numberOfHfills(Buffer const *, Row const * row) const;
618 /// like NumberOfHfills, but only those in the manual label!
619 int numberOfLabelHfills(Buffer const *, Row const * row) const;
620 /** returns true, if a expansion is needed. Rules are given by
623 bool hfillExpansion(Buffer const *, Row const * row_ptr,
624 Paragraph::size_type pos) const;
628 mutable std::vector<Paragraph::size_type> log2vis_list;
631 mutable std::vector<Paragraph::size_type> vis2log_list;
634 mutable std::vector<Paragraph::size_type> bidi_levels;
637 mutable Paragraph::size_type bidi_start;
640 mutable Paragraph::size_type bidi_end;
643 mutable bool bidi_same_direction;
646 unsigned char transformChar(unsigned char c, Paragraph * par,
647 Paragraph::size_type pos) const;
649 /** returns the paragraph position of the last character in the
652 Paragraph::size_type rowLast(Row const * row) const;
654 Paragraph::size_type rowLastPrintable(Row const * row) const;
659 // special owner functions
661 Paragraph * ownerParagraph() const;
663 Paragraph * ownerParagraph(Paragraph *) const;
667 /* returns a pointer to the row near the specified y-coordinate
668 * (relative to the whole text). y is set to the real beginning
671 Row * LyXText::getRowNearY(int & y) const
673 // If possible we should optimize this method. (Lgb)
674 Row * tmprow = firstrow;
677 while (tmprow->next() && tmpy + tmprow->height() <= y) {
678 tmpy += tmprow->height();
679 tmprow = tmprow->next();
682 y = tmpy; // return the real y