2 /* This file is part of
3 * ======================================================
5 * LyX, The Document Processor
7 * Copyright 1995 Matthias Ettrich
8 * Copyright 1995-2000 The LyX Team.
10 * ====================================================== */
21 #include "lyxcursor.h"
22 #include "lyxparagraph.h"
33 This class holds the mapping between buffer paragraphs and screen rows.
44 NEED_VERY_LITTLE_REFRESH,
50 LyXText(BufferView *);
57 void init(BufferView *);
59 mutable int number_of_rows;
63 mutable unsigned int width;
64 /// the current font settings
65 mutable LyXFont current_font;
67 mutable LyXFont real_current_font;
68 /// first visible pixel-row is set from LyXScreen!!!
69 // unsigned is wrong here for text-insets!
72 BufferView * bv_owner;
74 InsetText * inset_owner;
76 UpdatableInset * the_locking_inset;
79 int GetRealCursorX(BufferView *) const;
81 LyXFont const GetFont(Buffer const *, LyXParagraph * par,
82 LyXParagraph::size_type pos) const;
84 void SetCharFont(Buffer const *, LyXParagraph * par,
85 LyXParagraph::size_type pos,
86 LyXFont const & font);
87 /// returns a pointer to the very first LyXParagraph
88 LyXParagraph * FirstParagraph() const;
90 /// what you expect when pressing <enter> at cursor position
91 void BreakParagraph(BufferView *, char keep_layout = 0);
93 /** set layout over selection and make a total rebreak of
96 LyXParagraph * SetLayout(BufferView *, LyXCursor & actual_cursor,
97 LyXCursor & selection_start,
98 LyXCursor & selection_end,
99 LyXTextClass::size_type layout);
100 void SetLayout(BufferView *, LyXTextClass::size_type layout);
102 /// used in setlayout
103 void MakeFontEntriesLayoutSpecific(Buffer const *, LyXParagraph * par);
105 /** increment depth over selection and make a total rebreak of those
108 void IncDepth(BufferView *);
110 /** decrement depth over selection and make a total rebreak of those
112 void DecDepth(BufferView *);
114 /** Get the depth at current cursor position
116 int GetDepth() const { return cursor.par()->GetDepth(); }
118 /** set font over selection and make a total rebreak of those
120 toggleall defaults to false.
122 void SetFont(BufferView *, LyXFont const &, bool toggleall = false);
124 /** deletes and inserts again all paragaphs between the cursor
125 and the specified par. The Cursor is needed to set the refreshing
127 This function is needed after SetLayout and SetFont etc.
129 void RedoParagraphs(BufferView *, LyXCursor const & cursor,
130 LyXParagraph const * end_par) const;
132 void RedoParagraph(BufferView *) const;
135 void ToggleFree(BufferView *, LyXFont const &, bool toggleall = false);
137 /** recalculates the heights of all previous rows of the
138 specified paragraph. needed, if the last characters font
141 void RedoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
143 /** forces the redrawing of a paragraph. Needed when manipulating a
146 void RedoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
148 /** insert a character, moves all the following breaks in the
149 same Paragraph one to the right and make a little rebreak
151 void InsertChar(BufferView *, char c);
153 void InsertInset(BufferView *, Inset * inset);
155 /** Completes the insertion with a full rebreak.
156 Returns true if something was broken. */
157 bool FullRebreak(BufferView *);
160 Row * need_break_row;
162 mutable int refresh_y;
170 mutable Row * refresh_row;
174 /** wether the screen needs a refresh,
175 starting with refresh_y
177 mutable text_status status;
179 /** returns a pointer to the row near the specified y-coordinate
180 (relative to the whole text). y is set to the real beginning
183 Row * GetRowNearY(int & y) const;
185 /** returns the column near the specified x-coordinate of the row
186 x is set to the real beginning of this column
188 int GetColumnNearX(BufferView *, Row * row,
189 int & x, bool & boundary) const;
191 /** returns a pointer to a specified row. y is set to the beginning
194 Row * GetRow(LyXParagraph * par,
195 LyXParagraph::size_type pos, int & y) const;
197 /** returns the height of a default row, needed for scrollbar
199 int DefaultHeight() const;
202 Later this variable has to be removed. There should be now internal
203 cursor in a text (and thus not in a buffer). By keeping this it is
204 (I think) impossible to have several views with the same buffer, but
205 the cursor placed at different places.
207 Since the LyXText now has been moved from Buffer to BufferView
208 it should not be absolutely needed to move the cursor...
210 mutable LyXCursor cursor;
212 /* the selection cursor */
214 mutable bool selection;
216 mutable bool mark_set;
219 mutable LyXCursor sel_cursor;
221 LyXCursor sel_start_cursor;
223 mutable LyXCursor sel_end_cursor;
224 /// needed for the toggling
225 LyXCursor last_sel_cursor;
227 LyXCursor toggle_cursor;
229 LyXCursor toggle_end_cursor;
231 /// need the selection cursor:
232 void SetSelection(BufferView *);
234 void ClearSelection(BufferView *) const;
236 string const selectionAsString(Buffer const *) const;
238 /// just selects the word the cursor is in
239 void SelectWord(BufferView *);
241 /** 'selects" the next word, where the cursor is not in
242 and returns this word as string. THe cursor will be moved
243 to the beginning of this word.
244 With SelectSelectedWord can this be highlighted really
246 string const SelectNextWord(BufferView *, float & value) const;
248 void SelectSelectedWord(BufferView *);
250 void SetCursor(BufferView *, LyXParagraph * par,
251 LyXParagraph::size_type pos,
253 bool boundary = false) const;
255 void SetCursor(BufferView *, LyXCursor &, LyXParagraph * par,
256 LyXParagraph::size_type pos,
257 bool boundary = false) const;
259 void SetCursorIntern(BufferView *, LyXParagraph * par,
260 LyXParagraph::size_type pos,
262 bool boundary = false) const;
264 void SetCurrentFont(BufferView *) const;
267 bool IsBoundary(Buffer const *, LyXParagraph * par,
268 LyXParagraph::size_type pos) const;
270 bool IsBoundary(Buffer const *, LyXParagraph * par,
271 LyXParagraph::size_type pos,
272 LyXFont const & font) const;
275 void SetCursorFromCoordinates(BufferView *, int x, int y) const;
277 void SetCursorFromCoordinates(BufferView *, LyXCursor &,
280 void CursorUp(BufferView *) const;
282 void CursorDown(BufferView *) const;
284 void CursorLeft(BufferView *, bool internal = true) const;
286 void CursorRight(BufferView *, bool internal = true) const;
288 void CursorLeftOneWord(BufferView *) const;
290 void CursorRightOneWord(BufferView *) const;
292 void CursorUpParagraph(BufferView *) const;
294 void CursorDownParagraph(BufferView *) const;
296 void CursorHome(BufferView *) const;
298 void CursorEnd(BufferView *) const;
300 void CursorTab(BufferView *) const;
302 void CursorTop(BufferView *) const;
304 void CursorBottom(BufferView *) const;
306 void Delete(BufferView *);
308 void Backspace(BufferView *);
310 void DeleteWordForward(BufferView *);
312 void DeleteWordBackward(BufferView *);
314 void DeleteLineForward(BufferView *);
316 bool SelectWordWhenUnderCursor(BufferView *);
322 text_capitalization = 1,
326 /// Change the case of the word at cursor position.
327 void ChangeWordCase(BufferView *, TextCase action);
328 void TransposeChars(BufferView const &);
330 /** returns a printed row in a pixmap. The y value is needed to
331 decide, wether it is selected text or not. This is a strange
334 void GetVisibleRow(BufferView *, int y_offset, int x_offset,
335 Row * row_ptr, int y, bool cleared=false);
338 void CutSelection(BufferView *, bool = true);
340 void CopySelection(BufferView *);
342 void PasteSelection(BufferView *);
344 void copyEnvironmentType();
346 void pasteEnvironmentType(BufferView *);
348 void InsertFootnote();
350 void InsertMarginpar();
354 void InsertTabular();
356 /** the DTP switches for paragraphs. LyX will store the top settings
357 always in the first physical paragraph, the bottom settings in the
358 last. When a paragraph is broken, the top settings rest, the bottom
359 settings are given to the new one. So I can make shure, they do not
360 duplicate themself (and you cannnot make dirty things with them! )
362 void SetParagraph(BufferView *,
363 bool line_top, bool line_bottom,
364 bool pagebreak_top, bool pagebreak_bottom,
365 VSpace const & space_top,
366 VSpace const & space_bottom,
368 string labelwidthstring,
371 /* these things are for search and replace */
373 /** sets the selection over the number of characters of string,
376 void SetSelectionOverString(BufferView *, string const & str);
378 /** simple replacing. The font of the first selected character
381 void ReplaceSelectionWithString(BufferView *, string const & str);
383 /// needed to insert the selection
384 void InsertStringA(BufferView *, string const & str);
385 /// needed to insert the selection
386 void InsertStringB(BufferView *, string const & str);
388 /// Find next inset of some specified type.
389 bool GotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
390 string const & contents = string()) const;
393 /* for the greater insets */
395 /// returns false if inset wasn't found
396 bool UpdateInset(BufferView *, Inset *);
398 void CheckParagraph(BufferView *, LyXParagraph * par,
399 LyXParagraph::size_type pos);
401 int NumberOfCell(LyXParagraph * par,
402 LyXParagraph::size_type pos) const;
404 LyXParagraph * GetParFromID(int id);
407 /// returns false if no undo possible
408 bool TextUndo(BufferView *);
409 /// returns false if no redo possible
410 bool TextRedo(BufferView *);
411 /// used by TextUndo/TextRedo
412 bool TextHandleUndo(BufferView *, Undo * undo);
413 /// makes sure the next operation will be stored
415 /// this is dangerous and for internal use only
417 /// this is dangerous and for internal use only
419 /// the flag used by FinishUndo();
420 mutable bool undo_finished;
424 void SetUndo(Buffer *, Undo::undo_kind kind,
425 LyXParagraph const * before,
426 LyXParagraph const * end) const;
428 void SetRedo(Buffer *, Undo::undo_kind kind,
429 LyXParagraph const * before,
430 LyXParagraph const * end);
432 Undo * CreateUndo(Buffer *, Undo::undo_kind kind,
433 LyXParagraph const * before,
434 LyXParagraph const * end) const;
435 /// for external use in lyx_cb.C
436 void SetCursorParUndo(Buffer *);
438 void RemoveTableRow(LyXCursor & cursor) const;
440 bool IsEmptyTableCell() const;
442 void toggleAppendix(BufferView *);
444 int workWidth(BufferView *) const;
446 void ComputeBidiTables(Buffer const *, Row * row) const;
448 /// Maps positions in the visual string to positions in logical string.
450 LyXParagraph::size_type log2vis(LyXParagraph::size_type pos) const {
451 if (bidi_start == -1)
454 return log2vis_list[pos-bidi_start];
457 /// Maps positions in the logical string to positions in visual string.
459 LyXParagraph::size_type vis2log(LyXParagraph::size_type pos) const {
460 if (bidi_start == -1)
463 return vis2log_list[pos-bidi_start];
467 LyXParagraph::size_type bidi_level(LyXParagraph::size_type pos) const {
468 if (bidi_start == -1)
471 return bidi_levels[pos-bidi_start];
475 bool bidi_InRange(LyXParagraph::size_type pos) const {
476 return bidi_start == -1 ||
477 (bidi_start <= pos && pos <= bidi_end);
483 mutable Row * firstrow;
485 mutable Row * lastrow;
487 /** Copybuffer for copy environment type.
488 Asger has learned that this should be a buffer-property instead
489 Lgb has learned that 'char' is a lousy type for non-characters
491 LyXTextClass::size_type copylayouttype;
493 /** inserts a new row behind the specified row, increments
494 the touched counters */
495 void InsertRow(Row * row, LyXParagraph * par,
496 LyXParagraph::size_type pos) const;
497 /** removes the row and reset the touched counters */
498 void RemoveRow(Row * row) const;
500 /** remove all following rows of the paragraph of the specified row. */
501 void RemoveParagraph(Row * row) const;
503 /** insert the specified paragraph behind the specified row */
504 void InsertParagraph(BufferView *,
505 LyXParagraph * par, Row * row) const;
507 /** appends the implizit specified paragraph behind the specified row,
508 * start at the implizit given position */
509 void AppendParagraph(BufferView *, Row * row) const;
512 void BreakAgain(BufferView *, Row * row) const;
514 void BreakAgainOneRow(BufferView *, Row * row);
515 /// Calculate and set the height of the row
516 void SetHeightOfRow(BufferView *, Row * row_ptr) const;
518 /** this calculates the specified parameters. needed when setting
519 * the cursor and when creating a visible row */
520 void PrepareToPrint(BufferView *, Row * row, float & x,
521 float & fill_separator,
523 float & fill_label_hfill,
524 bool bidi = true) const;
527 void DeleteEmptyParagraphMechanism(BufferView *,
528 LyXCursor const & old_cursor) const;
530 /** Updates all counters starting BEHIND the row. Changed paragraphs
531 * with a dynamic left margin will be rebroken. */
532 void UpdateCounters(BufferView *, Row * row) const;
534 void SetCounter(Buffer const *, LyXParagraph * par) const;
537 * some low level functions
541 int SingleWidth(BufferView *, LyXParagraph * par,
542 LyXParagraph::size_type pos) const;
544 int SingleWidth(BufferView *, LyXParagraph * par,
545 LyXParagraph::size_type pos, char c) const;
547 void draw(BufferView *, Row const * row,
548 LyXParagraph::size_type & pos,
549 int offset, float & x, bool cleared);
551 /// get the next breakpoint in a given paragraph
552 LyXParagraph::size_type NextBreakPoint(BufferView *, Row const * row,
554 /// returns the minimum space a row needs on the screen in pixel
555 int Fill(BufferView *, Row * row, int workwidth) const;
557 /** returns the minimum space a manual label needs on the
559 int LabelFill(BufferView *, Row const * row) const;
562 LyXParagraph::size_type
563 BeginningOfMainBody(Buffer const *, LyXParagraph const * par) const;
565 /** Returns the left beginning of the text.
566 This information cannot be taken from the layouts-objekt, because
567 in LaTeX the beginning of the text fits in some cases
568 (for example sections) exactly the label-width.
570 int LeftMargin(BufferView *, Row const * row) const;
572 int RightMargin(Buffer const *, Row const * row) const;
574 int LabelEnd (BufferView *, Row const * row) const;
576 /** returns the number of separators in the specified row.
577 The separator on the very last column doesnt count
579 int NumberOfSeparators(Buffer const *, Row const * row) const;
581 /** returns the number of hfills in the specified row. The
582 LyX-Hfill is a LaTeX \hfill so that the hfills at the
583 beginning and at the end were ignored. This is {\em MUCH}
584 more usefull than not to ignore!
586 int NumberOfHfills(Buffer const *, Row const * row) const;
588 /// like NumberOfHfills, but only those in the manual label!
589 int NumberOfLabelHfills(Buffer const *, Row const * row) const;
590 /** returns true, if a expansion is needed. Rules are given by
593 bool HfillExpansion(Buffer const *, Row const * row_ptr,
594 LyXParagraph::size_type pos) const;
598 mutable std::vector<LyXParagraph::size_type> log2vis_list;
601 mutable std::vector<LyXParagraph::size_type> vis2log_list;
604 mutable std::vector<LyXParagraph::size_type> bidi_levels;
607 mutable LyXParagraph::size_type bidi_start;
610 mutable LyXParagraph::size_type bidi_end;
613 mutable bool bidi_same_direction;
616 unsigned char TransformChar(unsigned char c, LyXParagraph * par,
617 LyXParagraph::size_type pos) const;
619 /** returns the paragraph position of the last character in the
622 LyXParagraph::size_type RowLast(Row const * row) const;
624 LyXParagraph::size_type RowLastPrintable(Row const * row) const;
629 // special owner functions
631 LyXParagraph * OwnerParagraph() const;
633 LyXParagraph * OwnerParagraph(LyXParagraph *) const;
637 /* returns a pointer to the row near the specified y-coordinate
638 * (relative to the whole text). y is set to the real beginning
641 Row * LyXText::GetRowNearY(int & y) const
643 // If possible we should optimize this method. (Lgb)
644 Row * tmprow = firstrow;
647 while (tmprow->next() && tmpy + tmprow->height() <= y) {
648 tmpy += tmprow->height();
649 tmprow = tmprow->next();
652 y = tmpy; // return the real y