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"
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 *);
66 /// sets inset as owner
72 void init(BufferView *, bool reinit = false);
76 mutable unsigned int width;
77 /// the current font settings
78 mutable LyXFont current_font;
80 mutable LyXFont real_current_font;
81 /// first visible pixel-row is set from LyXScreen!!!
82 // unsigned is wrong here for text-insets!
85 InsetText * inset_owner;
87 UpdatableInset * the_locking_inset;
90 int getRealCursorX(BufferView *) const;
92 LyXFont const getFont(Buffer const *, Paragraph * par,
93 lyx::pos_type pos) const;
95 LyXFont const getLayoutFont(Buffer const *, Paragraph * par) const;
97 LyXFont const getLabelFont(Buffer const *, Paragraph * par) const;
99 void setCharFont(Buffer const *, Paragraph * par,
100 lyx::pos_type pos, LyXFont const & font);
101 void setCharFont(BufferView *, Paragraph * par,
102 lyx::pos_type pos, LyXFont const & font, bool toggleall);
104 /// return true if the row changed
105 void markChangeInDraw(BufferView * bv, Row * row, Row * next);
107 void breakAgainOneRow(BufferView *, Row * row);
108 /// what you expect when pressing <enter> at cursor position
109 void breakParagraph(BufferView *, char keep_layout = 0);
111 /** set layout over selection and make a total rebreak of
114 Paragraph * setLayout(BufferView *, LyXCursor & actual_cursor,
115 LyXCursor & selection_start,
116 LyXCursor & selection_end,
117 string const & layout);
119 void setLayout(BufferView *, string const & layout);
121 /** increment depth over selection and make a total rebreak of those
124 void incDepth(BufferView *);
126 /** decrement depth over selection and make a total rebreak of those
128 void decDepth(BufferView *);
130 /// get the depth at current cursor position
131 int getDepth() const;
133 /** set font over selection and make a total rebreak of those
135 toggleall defaults to false.
137 void setFont(BufferView *, LyXFont const &, bool toggleall = false);
139 /** deletes and inserts again all paragaphs between the cursor
140 and the specified par. The Cursor is needed to set the refreshing
142 This function is needed after SetLayout and SetFont etc.
144 void redoParagraphs(BufferView *, LyXCursor const & cursor,
145 Paragraph const * end_par) const;
147 void redoParagraph(BufferView *) const;
150 void toggleFree(BufferView *, LyXFont const &, bool toggleall = false);
153 string getStringToIndex(BufferView *);
155 /** recalculates the heights of all previous rows of the
156 specified paragraph. needed, if the last characters font
159 void redoHeightOfParagraph(BufferView *, LyXCursor const & cursor);
161 /** insert a character, moves all the following breaks in the
162 same Paragraph one to the right and make a little rebreak
164 void insertChar(BufferView *, char c);
166 void insertInset(BufferView *, Inset * inset);
168 /// Completes the insertion with a full rebreak
169 void fullRebreak(BufferView *);
172 mutable Row * need_break_row;
174 mutable int refresh_y;
176 mutable Row * refresh_row;
178 /// give and set the LyXText status
179 text_status status() const;
181 void status(BufferView *, text_status) const;
184 Inset::RESULT dispatch(FuncRequest const & cmd);
187 /// only the top-level LyXText has this non-zero
188 BufferView * bv_owner;
190 /** wether the screen needs a refresh,
191 starting with refresh_y
193 mutable text_status status_;
196 /** returns a pointer to the row near the specified y-coordinate
197 (relative to the whole text). y is set to the real beginning
200 Row * getRowNearY(int & y) const;
202 /** returns the column near the specified x-coordinate of the row
203 x is set to the real beginning of this column
205 lyx::pos_type getColumnNearX(BufferView *, Row * row,
206 int & x, bool & boundary) const;
208 /** returns a pointer to a specified row. y is set to the beginning
211 Row * getRow(Paragraph * par, lyx::pos_type pos, int & y) const;
212 /** returns the firstrow, this could be done with the above too but
213 IMO it's stupid to have to allocate a dummy y all the time I need
216 Row * firstRow() { return firstrow; }
219 Later this variable has to be removed. There should be now internal
220 cursor in a text (and thus not in a buffer). By keeping this it is
221 (I think) impossible to have several views with the same buffer, but
222 the cursor placed at different places.
224 Since the LyXText now has been moved from Buffer to BufferView
225 it should not be absolutely needed to move the cursor...
227 mutable LyXCursor cursor; // actual cursor position
229 /** The structure that keeps track of the selections set. */
232 : set_(false), mark_(false)
246 LyXCursor cursor; // temporary cursor to hold a cursor position
247 // until setSelection is called!
248 LyXCursor start; // start of a REAL selection
249 LyXCursor end; // end of a REAL selection
251 bool set_; // former selection
252 bool mark_; // former mark_set
255 mutable Selection selection;
256 // this is used to handle XSelection events in the right manner
257 mutable Selection xsel_cache;
259 /// needed for the toggling (cursor position on last selection made)
260 mutable LyXCursor last_sel_cursor;
261 /// needed for toggling the selection in screen.C
262 mutable LyXCursor toggle_cursor;
263 /// needed for toggling the selection in screen.C
264 mutable LyXCursor toggle_end_cursor;
266 /// need the selection cursor:
267 void setSelection(BufferView *);
269 void clearSelection() const;
271 string const selectionAsString(Buffer const *, bool label) const;
273 /// select the word we need depending on word_location
274 void getWord(LyXCursor & from, LyXCursor & to,
275 word_location const) const;
276 /// just selects the word the cursor is in
277 void selectWord(BufferView *, word_location const);
278 /// returns the inset at cursor (if it exists), 0 otherwise
279 Inset * getInset() const;
281 /// accept selected change
282 void acceptChange(BufferView * bv);
284 /// reject selected change
285 void rejectChange(BufferView * bv);
287 /** 'selects" the next word, where the cursor is not in
288 and returns this word as string. THe cursor will be moved
289 to the beginning of this word.
290 With SelectSelectedWord can this be highlighted really
292 WordLangTuple const selectNextWordToSpellcheck(BufferView *, float & value) const;
294 void selectSelectedWord(BufferView *);
295 /// returns true if par was empty and was removed
296 bool setCursor(BufferView *, Paragraph * par,
299 bool boundary = false) const;
301 void setCursor(BufferView *, LyXCursor &, Paragraph * par,
303 bool boundary = false) const;
305 void setCursorIntern(BufferView *, Paragraph * par,
308 bool boundary = false) const;
310 void setCurrentFont(BufferView *) const;
313 bool isBoundary(Buffer const *, Paragraph * par,
314 lyx::pos_type pos) const;
316 bool isBoundary(Buffer const *, Paragraph * par,
318 LyXFont const & font) const;
321 void setCursorFromCoordinates(BufferView *, int x, int y) const;
323 void setCursorFromCoordinates(BufferView *, LyXCursor &,
326 void cursorUp(BufferView *, bool selecting = false) const;
328 void cursorDown(BufferView *, bool selecting = false) const;
330 void cursorLeft(BufferView *, bool internal = true) const;
332 void cursorRight(BufferView *, bool internal = true) const;
334 void cursorLeftOneWord(BufferView *) const;
336 void cursorRightOneWord(BufferView *) const;
338 void cursorUpParagraph(BufferView *) const;
340 void cursorDownParagraph(BufferView *) const;
342 void cursorHome(BufferView *) const;
344 void cursorEnd(BufferView *) const;
346 void cursorPrevious(BufferView * bv);
348 void cursorNext(BufferView * bv);
350 void cursorTab(BufferView *) const;
352 void cursorTop(BufferView *) const;
354 void cursorBottom(BufferView *) const;
356 void Delete(BufferView *);
358 void backspace(BufferView *);
360 bool selectWordWhenUnderCursor(BufferView *,
361 word_location const);
367 text_capitalization = 1,
371 /// Change the case of the word at cursor position.
372 void changeCase(BufferView &, TextCase action);
374 void transposeChars(BufferView &);
377 void toggleInset(BufferView *);
379 void cutSelection(BufferView *, bool doclear = true, bool realcut = true);
381 void copySelection(BufferView *);
383 void pasteSelection(BufferView *);
385 void copyEnvironmentType();
387 void pasteEnvironmentType(BufferView *);
389 /** the DTP switches for paragraphs. LyX will store the top settings
390 always in the first physical paragraph, the bottom settings in the
391 last. When a paragraph is broken, the top settings rest, the bottom
392 settings are given to the new one. So I can make shure, they do not
393 duplicate themself (and you cannnot make dirty things with them! )
395 void setParagraph(BufferView *,
396 bool line_top, bool line_bottom,
397 bool pagebreak_top, bool pagebreak_bottom,
398 VSpace const & space_top,
399 VSpace const & space_bottom,
400 Spacing const & spacing,
402 string labelwidthstring,
405 /* these things are for search and replace */
408 * Sets the selection from the current cursor position to length
409 * characters to the right. No safety checks.
411 void setSelectionRange(BufferView *, lyx::pos_type length);
413 /** simple replacing. The font of the first selected character
416 void replaceSelectionWithString(BufferView *, string const & str);
418 /// needed to insert the selection
419 void insertStringAsLines(BufferView *, string const & str);
420 /// needed to insert the selection
421 void insertStringAsParagraphs(BufferView *, string const & str);
423 /// Find next inset of some specified type.
424 bool gotoNextInset(BufferView *, std::vector<Inset::Code> const & codes,
425 string const & contents = string()) const;
427 void gotoInset(BufferView * bv, std::vector<Inset::Code> const & codes,
430 void gotoInset(BufferView * bv, Inset::Code code, bool same_content);
433 /* for the greater insets */
435 /// returns false if inset wasn't found
436 bool updateInset(BufferView *, Inset *);
438 void checkParagraph(BufferView *, Paragraph * par, lyx::pos_type pos);
440 int workWidth(BufferView &) const;
442 int workWidth(BufferView &, Inset * inset) const;
444 void computeBidiTables(Buffer const *, Row * row) const;
446 /// Maps positions in the visual string to positions in logical string.
448 lyx::pos_type log2vis(lyx::pos_type pos) const {
449 if (bidi_start == -1)
452 return log2vis_list[pos-bidi_start];
455 /// Maps positions in the logical string to positions in visual string.
457 lyx::pos_type vis2log(lyx::pos_type pos) const {
458 if (bidi_start == -1)
461 return vis2log_list[pos-bidi_start];
465 lyx::pos_type bidi_level(lyx::pos_type pos) const {
466 if (bidi_start == -1)
469 return bidi_levels[pos-bidi_start];
473 bool bidi_InRange(lyx::pos_type pos) const {
474 return bidi_start == -1 ||
475 (bidi_start <= pos && pos <= bidi_end);
479 mutable Row * firstrow;
481 mutable Row * lastrow;
484 void cursorLeftOneWord(LyXCursor &) const;
487 float getCursorX(BufferView *, Row *, lyx::pos_type pos,
488 lyx::pos_type last, bool boundary) const;
489 /// used in setlayout
490 void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
492 /** forces the redrawing of a paragraph. Needed when manipulating a
495 void redoDrawingOfParagraph(BufferView *, LyXCursor const & cursor);
497 /** Copybuffer for copy environment type.
498 Asger has learned that this should be a buffer-property instead
499 Lgb has learned that 'char' is a lousy type for non-characters
501 string copylayouttype;
503 /** inserts a new row behind the specified row, increments
504 the touched counters */
505 void insertRow(Row * row, Paragraph * par, lyx::pos_type pos) const;
506 /// removes the row and reset the touched counters
507 void removeRow(Row * row) const;
509 /// remove all following rows of the paragraph of the specified row.
510 void removeParagraph(Row * row) const;
512 /// insert the specified paragraph behind the specified row
513 void insertParagraph(BufferView *,
514 Paragraph * par, Row * row) const;
516 /** appends the implizit specified paragraph behind the specified row,
517 * start at the implizit given position */
518 void appendParagraph(BufferView *, Row * row) const;
521 void breakAgain(BufferView *, Row * row) const;
522 /// Calculate and set the height of the row
523 void setHeightOfRow(BufferView *, Row * row_ptr) const;
525 // fix the cursor `cur' after a characters has been deleted at `where'
526 // position. Called by deleteEmptyParagraphMechanism
527 void fixCursorAfterDelete(BufferView * bv,
529 LyXCursor const & where) const;
531 /// delete double space (false) or empty paragraphs (true) around old_cursor
532 bool deleteEmptyParagraphMechanism(BufferView *,
533 LyXCursor const & old_cursor) const;
536 /** Updates all counters starting BEHIND the row. Changed paragraphs
537 * with a dynamic left margin will be rebroken. */
538 void updateCounters(BufferView *) const;
540 void update(BufferView * bv, bool changed = true);
542 * Returns an inset if inset was hit, or 0 if not.
543 * If hit, the coordinates are changed relative to the inset.
545 Inset * checkInsetHit(BufferView * bv, int & x, int & y) const;
548 int singleWidth(BufferView *, Paragraph * par,
549 lyx::pos_type pos) const;
551 int singleWidth(BufferView *, Paragraph * par,
552 lyx::pos_type pos, char c) const;
554 /// return the color of the canvas
555 LColor::color backgroundColor() const;
558 mutable bool bidi_same_direction;
560 unsigned char transformChar(unsigned char c, Paragraph * par,
561 lyx::pos_type pos) const;
564 * Returns the left beginning of the text.
565 * This information cannot be taken from the layout object, because
566 * in LaTeX the beginning of the text fits in some cases
567 * (for example sections) exactly the label-width.
569 int leftMargin(BufferView *, Row const * row) const;
571 int rightMargin(Buffer const &, Row const & row) const;
573 /** this calculates the specified parameters. needed when setting
574 * the cursor and when creating a visible row */
575 void prepareToPrint(BufferView *, Row * row, float & x,
576 float & fill_separator,
578 float & fill_label_hfill,
579 bool bidi = true) const;
583 void setCounter(Buffer const *, Paragraph * par) const;
585 void deleteWordForward(BufferView *);
587 void deleteWordBackward(BufferView *);
589 void deleteLineForward(BufferView *);
592 * some low level functions
596 /// get the next breakpoint in a given paragraph
597 lyx::pos_type nextBreakPoint(BufferView *, Row const * row, int width) const;
598 /// returns the minimum space a row needs on the screen in pixel
599 int fill(BufferView &, Row & row, int workwidth) const;
602 * returns the minimum space a manual label needs on the
605 int labelFill(BufferView &, Row const & row) const;
608 int labelEnd(BufferView &, Row const & row) const;
611 mutable std::vector<lyx::pos_type> log2vis_list;
614 mutable std::vector<lyx::pos_type> vis2log_list;
617 mutable std::vector<lyx::pos_type> bidi_levels;
620 mutable lyx::pos_type bidi_start;
623 mutable lyx::pos_type bidi_end;
629 // special owner functions
631 Paragraph * ownerParagraph() const;
633 void ownerParagraph(Paragraph *) const;
634 // set it searching first for the right owner using the paragraph id
635 void ownerParagraph(int id, Paragraph *) const;
637 /// return true if this is the outer-most lyxtext
638 bool isTopLevel() const;
640 /// return true if this is owned by an inset. FIXME: why the difference
641 /// with isTopLevel() ??
642 bool isInInset() const;
645 /// return the default height of a row in pixels, considering font zoom
646 extern int defaultRowHeight();