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 * ====================================================== */
16 #include "lyxcursor.h"
19 #include "insets/inset.h"
35 This class holds the mapping between buffer paragraphs and screen rows.
46 NEED_VERY_LITTLE_REFRESH = 2,
52 // the word around the cursor, only if the cursor is
55 // the word around the cursor
57 /// the word begining from the cursor position
59 /// the word around the cursor or before the cursor
61 /// the next word (not yet used)
66 LyXText(BufferView *);
67 /// sets inset as owner
73 void init(BufferView *, bool reinit = false);
77 mutable unsigned int width;
78 /// the current font settings
79 mutable LyXFont current_font;
81 mutable LyXFont real_current_font;
82 /// first visible pixel-row is set from LyXScreen!!!
83 // unsigned is wrong here for text-insets!
86 InsetText * inset_owner;
88 UpdatableInset * the_locking_inset;
91 int getRealCursorX(BufferView *) const;
93 LyXFont const getFont(Buffer const *, Paragraph * par,
94 lyx::pos_type pos) const;
96 LyXFont const getLayoutFont(Buffer const *, Paragraph * par) const;
98 LyXFont const getLabelFont(Buffer const *, Paragraph * par) const;
100 void setCharFont(Buffer const *, Paragraph * par,
101 lyx::pos_type pos, LyXFont const & font);
102 void setCharFont(BufferView *, Paragraph * par,
103 lyx::pos_type pos, LyXFont const & font, bool toggleall);
105 /// return true if the row changed
106 void markChangeInDraw(BufferView * bv, Row * row, Row * next);
108 void breakAgainOneRow(BufferView *, Row * row);
109 /// what you expect when pressing <enter> at cursor position
110 void breakParagraph(BufferView *,
111 ParagraphList & paragraphs, char keep_layout = 0);
113 /** set layout over selection and make a total rebreak of
116 Paragraph * setLayout(BufferView *, LyXCursor & actual_cursor,
117 LyXCursor & selection_start,
118 LyXCursor & selection_end,
119 string const & layout);
121 void setLayout(BufferView *, string const & layout);
123 /** increment depth over selection and make a total rebreak of those
126 void incDepth(BufferView *);
128 /** decrement depth over selection and make a total rebreak of those
130 void decDepth(BufferView *);
132 /// get the depth at current cursor position
133 int getDepth() const;
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 /** insert a character, moves all the following breaks in the
164 same Paragraph one to the right and make a little rebreak
166 void insertChar(BufferView *, char c);
168 void insertInset(BufferView *, Inset * inset);
170 /// Completes the insertion with a full rebreak
171 void fullRebreak(BufferView *);
174 mutable Row * need_break_row;
176 mutable int refresh_y;
178 mutable Row * refresh_row;
180 /// give and set the LyXText status
181 text_status status() const;
183 void status(BufferView *, text_status) const;
186 Inset::RESULT dispatch(FuncRequest const & cmd);
189 /// only the top-level LyXText has this non-zero
190 BufferView * bv_owner;
192 /** wether the screen needs a refresh,
193 starting with refresh_y
195 mutable text_status status_;
198 /** returns a pointer to the row near the specified y-coordinate
199 (relative to the whole text). y is set to the real beginning
202 Row * getRowNearY(int & y) const;
204 /** returns the column near the specified x-coordinate of the row
205 x is set to the real beginning of this column
207 lyx::pos_type getColumnNearX(BufferView *, Row * row,
208 int & x, bool & boundary) const;
210 /** returns a pointer to a specified row. y is set to the beginning
213 Row * getRow(Paragraph * par, lyx::pos_type pos, int & y) const;
214 /** returns the firstrow, this could be done with the above too but
215 IMO it's stupid to have to allocate a dummy y all the time I need
218 Row * firstRow() { return firstrow; }
221 Later this variable has to be removed. There should be now internal
222 cursor in a text (and thus not in a buffer). By keeping this it is
223 (I think) impossible to have several views with the same buffer, but
224 the cursor placed at different places.
226 Since the LyXText now has been moved from Buffer to BufferView
227 it should not be absolutely needed to move the cursor...
229 mutable LyXCursor cursor; // actual cursor position
231 /** The structure that keeps track of the selections set. */
234 : set_(false), mark_(false)
248 LyXCursor cursor; // temporary cursor to hold a cursor position
249 // until setSelection is called!
250 LyXCursor start; // start of a REAL selection
251 LyXCursor end; // end of a REAL selection
253 bool set_; // former selection
254 bool mark_; // former mark_set
257 mutable Selection selection;
258 // this is used to handle XSelection events in the right manner
259 mutable Selection xsel_cache;
261 /// needed for the toggling (cursor position on last selection made)
262 mutable LyXCursor last_sel_cursor;
263 /// needed for toggling the selection in screen.C
264 mutable LyXCursor toggle_cursor;
265 /// needed for toggling the selection in screen.C
266 mutable LyXCursor toggle_end_cursor;
268 /// need the selection cursor:
269 void setSelection(BufferView *);
271 void clearSelection() const;
273 string const selectionAsString(Buffer const *, bool label) const;
275 /// select the word we need depending on word_location
276 void getWord(LyXCursor & from, LyXCursor & to,
277 word_location const) const;
278 /// just selects the word the cursor is in
279 void selectWord(BufferView *, word_location const);
280 /// returns the inset at cursor (if it exists), 0 otherwise
281 Inset * getInset() const;
283 /// accept selected change
284 void acceptChange(BufferView * bv);
286 /// reject selected change
287 void rejectChange(BufferView * bv);
289 /** 'selects" the next word, where the cursor is not in
290 and returns this word as string. THe cursor will be moved
291 to the beginning of this word.
292 With SelectSelectedWord can this be highlighted really
294 WordLangTuple const selectNextWordToSpellcheck(BufferView *, float & value) const;
296 void selectSelectedWord(BufferView *);
297 /// returns true if par was empty and was removed
298 bool setCursor(BufferView *, Paragraph * par,
301 bool boundary = false) const;
303 void setCursor(BufferView *, LyXCursor &, Paragraph * par,
305 bool boundary = false) const;
307 void setCursorIntern(BufferView *, Paragraph * par,
310 bool boundary = false) const;
312 void setCurrentFont(BufferView *) const;
315 bool isBoundary(Buffer const *, Paragraph * par,
316 lyx::pos_type pos) const;
318 bool isBoundary(Buffer const *, Paragraph * par,
320 LyXFont const & font) const;
323 void setCursorFromCoordinates(BufferView *, int x, int y) const;
325 void setCursorFromCoordinates(BufferView *, LyXCursor &,
328 void cursorUp(BufferView *, bool selecting = false) const;
330 void cursorDown(BufferView *, bool selecting = false) const;
332 void cursorLeft(BufferView *, bool internal = true) const;
334 void cursorRight(BufferView *, bool internal = true) const;
336 void cursorLeftOneWord(BufferView *) const;
338 void cursorRightOneWord(BufferView *) const;
340 void cursorUpParagraph(BufferView *) const;
342 void cursorDownParagraph(BufferView *) const;
344 void cursorHome(BufferView *) const;
346 void cursorEnd(BufferView *) const;
348 void cursorPrevious(BufferView * bv);
350 void cursorNext(BufferView * bv);
352 void cursorTab(BufferView *) const;
354 void cursorTop(BufferView *) const;
356 void cursorBottom(BufferView *) const;
358 void Delete(BufferView *);
360 void backspace(BufferView *);
362 bool selectWordWhenUnderCursor(BufferView *,
363 word_location const);
369 text_capitalization = 1,
373 /// Change the case of the word at cursor position.
374 void changeCase(BufferView &, TextCase action);
376 void transposeChars(BufferView &);
379 void toggleInset(BufferView *);
381 void cutSelection(BufferView *, bool doclear = true, bool realcut = true);
383 void copySelection(BufferView *);
385 void pasteSelection(BufferView *);
387 void copyEnvironmentType();
389 void pasteEnvironmentType(BufferView *);
391 /** the DTP switches for paragraphs. LyX will store the top settings
392 always in the first physical paragraph, the bottom settings in the
393 last. When a paragraph is broken, the top settings rest, the bottom
394 settings are given to the new one. So I can make shure, they do not
395 duplicate themself (and you cannnot make dirty things with them! )
397 void setParagraph(BufferView *,
398 bool line_top, bool line_bottom,
399 bool pagebreak_top, bool pagebreak_bottom,
400 VSpace const & space_top,
401 VSpace const & space_bottom,
402 Spacing const & spacing,
404 string labelwidthstring,
407 /* these things are for search and replace */
410 * Sets the selection from the current cursor position to length
411 * characters to the right. No safety checks.
413 void setSelectionRange(BufferView *, lyx::pos_type length);
415 /** simple replacing. The font of the first selected character
418 void replaceSelectionWithString(BufferView *, string const & str);
420 /// needed to insert the selection
421 void insertStringAsLines(BufferView *, string const & str);
422 /// needed to insert the selection
423 void insertStringAsParagraphs(BufferView *, string const & str);
425 /// Find next inset of some specified type.
426 bool gotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
427 string const & contents = string()) const;
429 void gotoInset(BufferView * bv, std::vector<Inset::Code> const & codes,
432 void gotoInset(BufferView * bv, Inset::Code code, bool same_content);
435 /* for the greater insets */
437 /// returns false if inset wasn't found
438 bool updateInset(BufferView *, Inset *);
440 void checkParagraph(BufferView *, Paragraph * par, lyx::pos_type pos);
442 int workWidth(BufferView &) const;
444 int workWidth(BufferView &, Inset * inset) const;
446 void computeBidiTables(Buffer const *, Row * row) const;
448 /// Maps positions in the visual string to positions in logical string.
450 lyx::pos_type log2vis(lyx::pos_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 lyx::pos_type vis2log(lyx::pos_type pos) const {
460 if (bidi_start == -1)
463 return vis2log_list[pos-bidi_start];
467 lyx::pos_type bidi_level(lyx::pos_type pos) const {
468 if (bidi_start == -1)
471 return bidi_levels[pos-bidi_start];
475 bool bidi_InRange(lyx::pos_type pos) const {
476 return bidi_start == -1 ||
477 (bidi_start <= pos && pos <= bidi_end);
481 mutable Row * firstrow;
483 mutable Row * lastrow;
486 void cursorLeftOneWord(LyXCursor &) const;
489 float getCursorX(BufferView *, Row *, lyx::pos_type pos,
490 lyx::pos_type last, bool boundary) const;
491 /// used in setlayout
492 void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
494 /** forces the redrawing of a paragraph. Needed when manipulating a
497 void redoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
499 /** Copybuffer for copy environment type.
500 Asger has learned that this should be a buffer-property instead
501 Lgb has learned that 'char' is a lousy type for non-characters
503 string copylayouttype;
505 /** inserts a new row behind the specified row, increments
506 the touched counters */
507 void insertRow(Row * row, Paragraph * par, lyx::pos_type pos) const;
508 /// removes the row and reset the touched counters
509 void removeRow(Row * row) const;
511 /// remove all following rows of the paragraph of the specified row.
512 void removeParagraph(Row * row) const;
514 /// insert the specified paragraph behind the specified row
515 void insertParagraph(BufferView *,
516 Paragraph * par, Row * row) const;
518 /** appends the implizit specified paragraph behind the specified row,
519 * start at the implizit given position */
520 void appendParagraph(BufferView *, Row * row) const;
523 void breakAgain(BufferView *, Row * row) const;
524 /// Calculate and set the height of the row
525 void setHeightOfRow(BufferView *, Row * row_ptr) const;
527 // fix the cursor `cur' after a characters has been deleted at `where'
528 // position. Called by deleteEmptyParagraphMechanism
529 void fixCursorAfterDelete(BufferView * bv,
531 LyXCursor const & where) const;
533 /// delete double space (false) or empty paragraphs (true) around old_cursor
534 bool deleteEmptyParagraphMechanism(BufferView *,
535 LyXCursor const & old_cursor) const;
538 /** Updates all counters starting BEHIND the row. Changed paragraphs
539 * with a dynamic left margin will be rebroken. */
540 void updateCounters(BufferView *) const;
542 void update(BufferView * bv, bool changed = true);
544 * Returns an inset if inset was hit, or 0 if not.
545 * If hit, the coordinates are changed relative to the inset.
547 Inset * checkInsetHit(BufferView * bv, int & x, int & y) const;
550 int singleWidth(BufferView *, Paragraph * par,
551 lyx::pos_type pos) const;
553 int singleWidth(BufferView *, Paragraph * par,
554 lyx::pos_type pos, char c) const;
556 /// return the color of the canvas
557 LColor::color backgroundColor() const;
560 mutable bool bidi_same_direction;
562 unsigned char transformChar(unsigned char c, Paragraph * par,
563 lyx::pos_type pos) const;
566 * Returns the left beginning of the text.
567 * This information cannot be taken from the layout object, because
568 * in LaTeX the beginning of the text fits in some cases
569 * (for example sections) exactly the label-width.
571 int leftMargin(BufferView *, Row const * row) const;
573 int rightMargin(Buffer const &, Row const & row) const;
575 /** this calculates the specified parameters. needed when setting
576 * the cursor and when creating a visible row */
577 void prepareToPrint(BufferView *, Row * row, float & x,
578 float & fill_separator,
580 float & fill_label_hfill,
581 bool bidi = true) const;
585 void setCounter(Buffer const *, Paragraph * par) const;
587 void deleteWordForward(BufferView *);
589 void deleteWordBackward(BufferView *);
591 void deleteLineForward(BufferView *);
594 * some low level functions
598 /// get the next breakpoint in a given paragraph
599 lyx::pos_type nextBreakPoint(BufferView *, Row const * row, int width) const;
600 /// returns the minimum space a row needs on the screen in pixel
601 int fill(BufferView &, Row & row, int workwidth) const;
604 * returns the minimum space a manual label needs on the
607 int labelFill(BufferView &, Row const & row) const;
610 int labelEnd(BufferView &, Row const & row) const;
613 mutable std::vector<lyx::pos_type> log2vis_list;
616 mutable std::vector<lyx::pos_type> vis2log_list;
619 mutable std::vector<lyx::pos_type> bidi_levels;
622 mutable lyx::pos_type bidi_start;
625 mutable lyx::pos_type bidi_end;
631 // special owner functions
633 Paragraph * ownerParagraph() const;
635 void ownerParagraph(Paragraph *) const;
636 // set it searching first for the right owner using the paragraph id
637 void ownerParagraph(int id, Paragraph *) const;
639 /// return true if this is the outer-most lyxtext
640 bool isTopLevel() const;
642 /// return true if this is owned by an inset. FIXME: why the difference
643 /// with isTopLevel() ??
644 bool isInInset() const;
647 /// return the default height of a row in pixels, considering font zoom
648 extern int defaultRowHeight();