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 * ====================================================== */
20 #include "lyxcursor.h"
21 #include "paragraph.h"
34 This class holds the mapping between buffer paragraphs and screen rows.
45 NEED_VERY_LITTLE_REFRESH = 2,
51 // the word around the cursor, only if the cursor is
54 // the word around the cursor
56 /// the word begining from the cursor position
58 /// the word around the cursor or before the cursor
60 /// the next word (not yet used)
65 LyXText(BufferView *);
72 void init(BufferView *, bool reinit = false);
74 mutable int number_of_rows;
78 mutable unsigned int width;
79 /// the current font settings
80 mutable LyXFont current_font;
82 mutable LyXFont real_current_font;
83 /// first visible pixel-row is set from LyXScreen!!!
84 // unsigned is wrong here for text-insets!
87 BufferView * bv_owner;
89 InsetText * inset_owner;
91 UpdatableInset * the_locking_inset;
94 int getRealCursorX(BufferView *) const;
96 LyXFont const getFont(Buffer const *, Paragraph * par,
97 Paragraph::size_type pos) const;
99 void setCharFont(Buffer const *, Paragraph * par,
100 Paragraph::size_type pos, LyXFont const & font);
101 void setCharFont(BufferView *, Paragraph * par,
102 Paragraph::size_type pos,
103 LyXFont const & font, bool toggleall);
104 /// returns a pointer to the very first Paragraph
105 Paragraph * firstParagraph() const;
107 /// what you expect when pressing <enter> at cursor position
108 void breakParagraph(BufferView *, char keep_layout = 0);
110 /** set layout over selection and make a total rebreak of
113 Paragraph * setLayout(BufferView *, LyXCursor & actual_cursor,
114 LyXCursor & selection_start,
115 LyXCursor & selection_end,
116 LyXTextClass::size_type layout);
117 void setLayout(BufferView *, LyXTextClass::size_type layout);
119 /// used in setlayout
120 void makeFontEntriesLayoutSpecific(Buffer const *, Paragraph * par);
122 /** increment depth over selection and make a total rebreak of those
125 void incDepth(BufferView *);
127 /** decrement depth over selection and make a total rebreak of those
129 void decDepth(BufferView *);
131 /** Get the depth at current cursor position
133 int getDepth() const { return cursor.par()->getDepth(); }
135 /** set font over selection and make a total rebreak of those
137 toggleall defaults to false.
139 void setFont(BufferView *, LyXFont const &, bool toggleall = false);
141 /** deletes and inserts again all paragaphs between the cursor
142 and the specified par. The Cursor is needed to set the refreshing
144 This function is needed after SetLayout and SetFont etc.
146 void redoParagraphs(BufferView *, LyXCursor const & cursor,
147 Paragraph const * end_par) const;
149 void redoParagraph(BufferView *) const;
152 void toggleFree(BufferView *, LyXFont const &, bool toggleall = false);
155 string getStringToIndex(BufferView *);
157 /** recalculates the heights of all previous rows of the
158 specified paragraph. needed, if the last characters font
161 void redoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
163 /** forces the redrawing of a paragraph. Needed when manipulating a
166 void redoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
168 /** insert a character, moves all the following breaks in the
169 same Paragraph one to the right and make a little rebreak
171 void insertChar(BufferView *, char c);
173 void insertInset(BufferView *, Inset * inset);
175 /** Completes the insertion with a full rebreak.
176 Returns true if something was broken. */
177 bool fullRebreak(BufferView *);
180 Row * need_break_row;
182 mutable int refresh_y;
190 mutable Row * refresh_row;
194 /// give and set the LyXText status
195 text_status status() const;
197 void status(BufferView *, text_status) const;
200 /** wether the screen needs a refresh,
201 starting with refresh_y
203 mutable text_status status_;
206 /** returns a pointer to the row near the specified y-coordinate
207 (relative to the whole text). y is set to the real beginning
210 Row * getRowNearY(int & y) const;
212 /** returns the column near the specified x-coordinate of the row
213 x is set to the real beginning of this column
215 int getColumnNearX(BufferView *, Row * row,
216 int & x, bool & boundary) const;
218 /** returns a pointer to a specified row. y is set to the beginning
221 Row * getRow(Paragraph * par,
222 Paragraph::size_type pos, int & y) const;
224 /** returns the height of a default row, needed for scrollbar
226 int defaultHeight() const;
229 Later this variable has to be removed. There should be now internal
230 cursor in a text (and thus not in a buffer). By keeping this it is
231 (I think) impossible to have several views with the same buffer, but
232 the cursor placed at different places.
234 Since the LyXText now has been moved from Buffer to BufferView
235 it should not be absolutely needed to move the cursor...
237 mutable LyXCursor cursor;
239 /** The structrue that keeps track of the selections set. */
242 : set_(false), mark_(false)
260 bool set_; // former selection
261 bool mark_; // former mark_set
264 mutable Selection selection;
266 /// needed for the toggling
267 LyXCursor last_sel_cursor;
269 LyXCursor toggle_cursor;
271 LyXCursor toggle_end_cursor;
273 /// need the selection cursor:
274 void setSelection(BufferView *);
276 void clearSelection(BufferView *) const;
278 string const selectionAsString(Buffer const *) const;
280 /// select the word we need depending on word_location
281 void getWord(LyXCursor & from, LyXCursor & to,
282 word_location const) const;
283 /// just selects the word the cursor is in
284 void selectWord(BufferView *, word_location const);
285 /// returns the inset at cursor (if it exists), 0 otherwise
286 Inset * getInset() const;
288 /** 'selects" the next word, where the cursor is not in
289 and returns this word as string. THe cursor will be moved
290 to the beginning of this word.
291 With SelectSelectedWord can this be highlighted really
293 string const selectNextWord(BufferView *, float & value) const;
295 void selectSelectedWord(BufferView *);
297 void setCursor(BufferView *, Paragraph * par,
298 Paragraph::size_type pos,
300 bool boundary = false) const;
302 void setCursor(BufferView *, LyXCursor &, Paragraph * par,
303 Paragraph::size_type pos,
304 bool boundary = false) const;
306 void setCursorIntern(BufferView *, Paragraph * par,
307 Paragraph::size_type pos,
309 bool boundary = false) const;
311 void setCurrentFont(BufferView *) const;
314 bool isBoundary(Buffer const *, Paragraph * par,
315 Paragraph::size_type pos) const;
317 bool isBoundary(Buffer const *, Paragraph * par,
318 Paragraph::size_type pos,
319 LyXFont const & font) const;
322 void setCursorFromCoordinates(BufferView *, int x, int y) const;
324 void setCursorFromCoordinates(BufferView *, LyXCursor &,
327 void cursorUp(BufferView *) const;
329 void cursorDown(BufferView *) const;
331 void cursorLeft(BufferView *, bool internal = true) const;
333 void cursorRight(BufferView *, bool internal = true) const;
335 void cursorLeftOneWord(BufferView *) const;
337 void cursorLeftOneWord(LyXCursor &) const;
339 void cursorRightOneWord(BufferView *) const;
341 void cursorUpParagraph(BufferView *) const;
343 void cursorDownParagraph(BufferView *) const;
345 void cursorHome(BufferView *) const;
347 void cursorEnd(BufferView *) const;
349 void cursorTab(BufferView *) const;
351 void cursorTop(BufferView *) const;
353 void cursorBottom(BufferView *) const;
355 void Delete(BufferView *);
357 void backspace(BufferView *);
359 void deleteWordForward(BufferView *);
361 void deleteWordBackward(BufferView *);
363 void deleteLineForward(BufferView *);
365 bool selectWordWhenUnderCursor(BufferView *,
366 word_location const);
372 text_capitalization = 1,
376 /// Change the case of the word at cursor position.
377 void changeCase(BufferView *, TextCase action);
379 void changeRegionCase(BufferView * bview,
380 LyXCursor const & from,
381 LyXCursor const & to,
382 LyXText::TextCase action);
384 void transposeChars(BufferView &);
386 /** returns a printed row in a pixmap. The y value is needed to
387 decide, wether it is selected text or not. This is a strange
390 void getVisibleRow(BufferView *, int y_offset, int x_offset,
391 Row * row_ptr, int y, bool cleared=false);
394 void toggleInset(BufferView *);
396 void cutSelection(BufferView *, bool = true);
398 void copySelection(BufferView *);
400 void pasteSelection(BufferView *);
402 void copyEnvironmentType();
404 void pasteEnvironmentType(BufferView *);
406 /** the DTP switches for paragraphs. LyX will store the top settings
407 always in the first physical paragraph, the bottom settings in the
408 last. When a paragraph is broken, the top settings rest, the bottom
409 settings are given to the new one. So I can make shure, they do not
410 duplicate themself (and you cannnot make dirty things with them! )
412 void setParagraph(BufferView *,
413 bool line_top, bool line_bottom,
414 bool pagebreak_top, bool pagebreak_bottom,
415 VSpace const & space_top,
416 VSpace const & space_bottom,
418 string labelwidthstring,
421 /* these things are for search and replace */
423 /** sets the selection over the number of characters of string,
426 void setSelectionOverString(BufferView *, string const & str);
428 /** simple replacing. The font of the first selected character
431 void replaceSelectionWithString(BufferView *, string const & str);
433 /// needed to insert the selection
434 void insertStringAsLines(BufferView *, string const & str);
435 /// needed to insert the selection
436 void insertStringAsParagraphs(BufferView *, string const & str);
438 /// Find next inset of some specified type.
439 bool gotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
440 string const & contents = string()) const;
443 /* for the greater insets */
445 /// returns false if inset wasn't found
446 bool updateInset(BufferView *, Inset *);
448 void checkParagraph(BufferView *, Paragraph * par,
449 Paragraph::size_type pos);
451 int numberOfCell(Paragraph * par,
452 Paragraph::size_type pos) const;
454 void removeTableRow(LyXCursor & cursor) const;
456 bool isEmptyTableCell() const;
458 void toggleAppendix(BufferView *);
460 int workWidth(BufferView *) const;
462 void computeBidiTables(Buffer const *, Row * row) const;
464 /// Maps positions in the visual string to positions in logical string.
466 Paragraph::size_type log2vis(Paragraph::size_type pos) const {
467 if (bidi_start == -1)
470 return log2vis_list[pos-bidi_start];
473 /// Maps positions in the logical string to positions in visual string.
475 Paragraph::size_type vis2log(Paragraph::size_type pos) const {
476 if (bidi_start == -1)
479 return vis2log_list[pos-bidi_start];
483 Paragraph::size_type bidi_level(Paragraph::size_type pos) const {
484 if (bidi_start == -1)
487 return bidi_levels[pos-bidi_start];
491 bool bidi_InRange(Paragraph::size_type pos) const {
492 return bidi_start == -1 ||
493 (bidi_start <= pos && pos <= bidi_end);
497 mutable Row * firstrow;
499 mutable Row * lastrow;
501 /** Copybuffer for copy environment type.
502 Asger has learned that this should be a buffer-property instead
503 Lgb has learned that 'char' is a lousy type for non-characters
505 LyXTextClass::size_type copylayouttype;
507 /** inserts a new row behind the specified row, increments
508 the touched counters */
509 void insertRow(Row * row, Paragraph * par,
510 Paragraph::size_type pos) const;
511 /** removes the row and reset the touched counters */
512 void removeRow(Row * row) const;
514 /** remove all following rows of the paragraph of the specified row. */
515 void removeParagraph(Row * row) const;
517 /** insert the specified paragraph behind the specified row */
518 void insertParagraph(BufferView *,
519 Paragraph * par, Row * row) const;
521 /** appends the implizit specified paragraph behind the specified row,
522 * start at the implizit given position */
523 void appendParagraph(BufferView *, Row * row) const;
526 void breakAgain(BufferView *, Row * row) const;
528 void breakAgainOneRow(BufferView *, Row * row);
529 /// Calculate and set the height of the row
530 void setHeightOfRow(BufferView *, Row * row_ptr) const;
532 /** this calculates the specified parameters. needed when setting
533 * the cursor and when creating a visible row */
534 void prepareToPrint(BufferView *, Row * row, float & x,
535 float & fill_separator,
537 float & fill_label_hfill,
538 bool bidi = true) const;
541 void deleteEmptyParagraphMechanism(BufferView *,
542 LyXCursor const & old_cursor) const;
545 /** Updates all counters starting BEHIND the row. Changed paragraphs
546 * with a dynamic left margin will be rebroken. */
547 void updateCounters(BufferView *, Row * row) const;
550 void setCounter(Buffer const *, Paragraph * par) const;
553 * some low level functions
557 int singleWidth(BufferView *, Paragraph * par,
558 Paragraph::size_type pos) const;
560 int singleWidth(BufferView *, Paragraph * par,
561 Paragraph::size_type pos, char c) const;
563 void draw(BufferView *, Row const * row,
564 Paragraph::size_type & pos,
565 int offset, float & x, bool cleared);
567 /// get the next breakpoint in a given paragraph
568 Paragraph::size_type nextBreakPoint(BufferView *, Row const * row,
570 /// returns the minimum space a row needs on the screen in pixel
571 int fill(BufferView *, Row * row, int workwidth) const;
573 /** returns the minimum space a manual label needs on the
575 int labelFill(BufferView *, Row const * row) const;
579 beginningOfMainBody(Buffer const *, Paragraph const * par) const;
581 /** Returns the left beginning of the text.
582 This information cannot be taken from the layouts-objekt, because
583 in LaTeX the beginning of the text fits in some cases
584 (for example sections) exactly the label-width.
586 int leftMargin(BufferView *, Row const * row) const;
588 int rightMargin(Buffer const *, Row const * row) const;
590 int labelEnd (BufferView *, Row const * row) const;
592 /** returns the number of separators in the specified row.
593 The separator on the very last column doesnt count
595 int numberOfSeparators(Buffer const *, Row const * row) const;
597 /** returns the number of hfills in the specified row. The
598 LyX-Hfill is a LaTeX \hfill so that the hfills at the
599 beginning and at the end were ignored. This is {\em MUCH}
600 more usefull than not to ignore!
602 int numberOfHfills(Buffer const *, Row const * row) const;
604 /// like NumberOfHfills, but only those in the manual label!
605 int numberOfLabelHfills(Buffer const *, Row const * row) const;
606 /** returns true, if a expansion is needed. Rules are given by
609 bool hfillExpansion(Buffer const *, Row const * row_ptr,
610 Paragraph::size_type pos) const;
612 LColor::color backgroundColor();
616 mutable std::vector<Paragraph::size_type> log2vis_list;
619 mutable std::vector<Paragraph::size_type> vis2log_list;
622 mutable std::vector<Paragraph::size_type> bidi_levels;
625 mutable Paragraph::size_type bidi_start;
628 mutable Paragraph::size_type bidi_end;
631 mutable bool bidi_same_direction;
634 unsigned char transformChar(unsigned char c, Paragraph * par,
635 Paragraph::size_type pos) const;
637 /** returns the paragraph position of the last character in the
640 Paragraph::size_type rowLast(Row const * row) const;
642 Paragraph::size_type rowLastPrintable(Row const * row) const;
648 // special owner functions
650 Paragraph * ownerParagraph() const;
652 Paragraph * ownerParagraph(Paragraph *) const;
653 // set it searching first for the right owner using the paragraph id
654 Paragraph * ownerParagraph(int id, Paragraph *) const;
658 /* returns a pointer to the row near the specified y-coordinate
659 * (relative to the whole text). y is set to the real beginning
662 Row * LyXText::getRowNearY(int & y) const
664 // If possible we should optimize this method. (Lgb)
665 Row * tmprow = firstrow;
668 while (tmprow->next() && tmpy + tmprow->height() <= y) {
669 tmpy += tmprow->height();
670 tmprow = tmprow->next();
673 y = tmpy; // return the real y