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.
39 /// what repainting is needed
41 /// no repaint is needed
44 * A paint has caused a change in some rows
45 * and rebreaking is needed.
48 /// the refresh_row needs repainting
49 NEED_VERY_LITTLE_REFRESH = 2,
50 /// everything from refresh_y downwards needs repainting
56 // the word around the cursor, only if the cursor is
59 // the word around the cursor
61 /// the word begining from the cursor position
63 /// the word around the cursor or before the cursor
65 /// the next word (not yet used)
70 LyXText(BufferView *);
71 /// sets inset as owner
72 LyXText(BufferView *, InsetText *);
77 void init(BufferView *, bool reinit = false);
82 /// the current font settings
85 LyXFont real_current_font;
87 /** the first visible row on screen
90 /** the pixel offset with respect to this row of top_y
94 /// get the y coord. of the top of the screen (relative to doc start)
99 InsetText * inset_owner;
101 UpdatableInset * the_locking_inset;
104 int getRealCursorX() const;
106 LyXFont const getFont(Buffer const *, Paragraph * par,
107 lyx::pos_type pos) const;
109 LyXFont const getLayoutFont(Buffer const *, Paragraph * par) const;
111 LyXFont const getLabelFont(Buffer const *, Paragraph * par) const;
113 void setCharFont(Buffer const *, Paragraph * par,
114 lyx::pos_type pos, LyXFont const & font);
115 void setCharFont(Paragraph * par,
116 lyx::pos_type pos, LyXFont const & font, bool toggleall);
118 /// return true if the row changed
119 void markChangeInDraw(Row * row, Row * next);
121 void breakAgainOneRow(Row * row);
122 /// what you expect when pressing <enter> at cursor position
123 void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
125 /** set layout over selection and make a total rebreak of
128 Paragraph * setLayout(LyXCursor & actual_cursor,
129 LyXCursor & selection_start,
130 LyXCursor & selection_end,
131 string const & layout);
133 void setLayout(string const & layout);
135 /** increment depth over selection and make a total rebreak of those
140 /** decrement depth over selection and make a total rebreak of those
144 /// get the depth at current cursor position
145 int getDepth() const;
147 /** set font over selection and make a total rebreak of those
149 toggleall defaults to false.
151 void setFont(LyXFont const &, bool toggleall = false);
153 /** deletes and inserts again all paragaphs between the cursor
154 and the specified par. The Cursor is needed to set the refreshing
156 This function is needed after SetLayout and SetFont etc.
158 void redoParagraphs(LyXCursor const & cursor,
159 Paragraph const * end_par);
161 void redoParagraph();
164 void toggleFree(LyXFont const &, bool toggleall = false);
167 string getStringToIndex();
169 /** recalculates the heights of all previous rows of the
170 specified paragraph. needed, if the last characters font
173 void redoHeightOfParagraph();
175 /** insert a character, moves all the following breaks in the
176 same Paragraph one to the right and make a little rebreak
178 void insertChar(char c);
180 void insertInset(Inset * inset);
182 /// Completes the insertion with a full rebreak
186 Row * need_break_row;
188 /// clear any pending paints
191 /// post notice that we changed during a draw
192 void postChangedInDraw();
195 * Mark position y as the starting point for a repaint
197 void postPaint(int start_y);
200 * Mark the given row at position y as needing a repaint.
202 void postRowPaint(Row * row, int start_y);
205 Inset::RESULT dispatch(FuncRequest const & cmd);
209 BufferView * bv() const;
211 friend class LyXScreen;
214 * Return the status. This represents what repaints are
215 * pending after some operation (e.g. inserting a char).
217 text_status status() const;
221 * The pixel y position from which to repaint the screen.
222 * The position is absolute along the height of outermost
223 * lyxtext (I think). NEED_MORE_REFRESH and NEED_LITTLE_REFRESH
224 * repaints both use this as a starting point (if it's within
225 * the viewable portion of the lyxtext).
229 * The row from which to repaint the screen, used by screen.c.
230 * This must be set if the pending update is NEED_LITTLE_REFRESH.
231 * It doesn't make any difference for NEED_MORE_REFRESH.
238 /// only the top-level LyXText has this non-zero
239 BufferView * bv_owner;
242 /** returns a pointer to the row near the specified y-coordinate
243 (relative to the whole text). y is set to the real beginning
246 Row * getRowNearY(int & y) const;
248 /** returns the column near the specified x-coordinate of the row
249 x is set to the real beginning of this column
251 lyx::pos_type getColumnNearX(Row * row,
252 int & x, bool & boundary) const;
254 /** returns a pointer to a specified row. y is set to the beginning
257 Row * getRow(Paragraph * par, lyx::pos_type pos, int & y) const;
258 /** returns the firstrow, this could be done with the above too but
259 IMO it's stupid to have to allocate a dummy y all the time I need
262 Row * firstRow() const { return firstrow; }
265 Later this variable has to be removed. There should be now internal
266 cursor in a text (and thus not in a buffer). By keeping this it is
267 (I think) impossible to have several views with the same buffer, but
268 the cursor placed at different places.
270 Since the LyXText now has been moved from Buffer to BufferView
271 it should not be absolutely needed to move the cursor...
273 LyXCursor cursor; // actual cursor position
275 /** The structure that keeps track of the selections set. */
278 : set_(false), mark_(false)
292 LyXCursor cursor; // temporary cursor to hold a cursor position
293 // until setSelection is called!
294 LyXCursor start; // start of a REAL selection
295 LyXCursor end; // end of a REAL selection
297 bool set_; // former selection
298 bool mark_; // former mark_set
302 // this is used to handle XSelection events in the right manner
303 Selection xsel_cache;
305 /// needed for the toggling (cursor position on last selection made)
306 LyXCursor last_sel_cursor;
307 /// needed for toggling the selection in screen.C
308 LyXCursor toggle_cursor;
309 /// needed for toggling the selection in screen.C
310 LyXCursor toggle_end_cursor;
312 /// need the selection cursor:
315 void clearSelection();
317 string const selectionAsString(Buffer const *, bool label) const;
319 /// select the word we need depending on word_location
320 void getWord(LyXCursor & from, LyXCursor & to,
321 word_location const);
322 /// just selects the word the cursor is in
323 void selectWord(word_location const);
324 /// returns the inset at cursor (if it exists), 0 otherwise
325 Inset * getInset() const;
327 /// accept selected change
330 /// reject selected change
333 /** 'selects" the next word, where the cursor is not in
334 and returns this word as string. THe cursor will be moved
335 to the beginning of this word.
336 With SelectSelectedWord can this be highlighted really
338 WordLangTuple const selectNextWordToSpellcheck(float & value);
340 void selectSelectedWord();
341 /// returns true if par was empty and was removed
342 bool setCursor(Paragraph * par,
345 bool boundary = false);
347 void setCursor(LyXCursor &, Paragraph * par,
349 bool boundary = false);
351 void setCursorIntern(Paragraph * par,
354 bool boundary = false);
356 void setCurrentFont();
359 bool isBoundary(Buffer const *, Paragraph * par,
360 lyx::pos_type pos) const;
362 bool isBoundary(Buffer const *, Paragraph * par,
364 LyXFont const & font) const;
367 void setCursorFromCoordinates(int x, int y);
369 void setCursorFromCoordinates(LyXCursor &,
372 void cursorUp(bool selecting = false);
374 void cursorDown(bool selecting = false);
376 void cursorLeft(bool internal = true);
378 void cursorRight(bool internal = true);
380 void cursorLeftOneWord();
382 void cursorRightOneWord();
384 void cursorUpParagraph();
386 void cursorDownParagraph();
392 void cursorPrevious();
406 bool selectWordWhenUnderCursor(word_location);
412 text_capitalization = 1,
416 /// Change the case of the word at cursor position.
417 void changeCase(TextCase action);
419 void transposeChars();
424 void cutSelection(bool doclear = true, bool realcut = true);
426 void copySelection();
428 void pasteSelection();
430 void copyEnvironmentType();
432 void pasteEnvironmentType();
434 /** the DTP switches for paragraphs. LyX will store the top settings
435 always in the first physical paragraph, the bottom settings in the
436 last. When a paragraph is broken, the top settings rest, the bottom
437 settings are given to the new one. So I can make shure, they do not
438 duplicate themself (and you cannnot make dirty things with them! )
440 void setParagraph(bool line_top, bool line_bottom,
441 bool pagebreak_top, bool pagebreak_bottom,
442 VSpace const & space_top,
443 VSpace const & space_bottom,
444 Spacing const & spacing,
446 string const & labelwidthstring,
449 /* these things are for search and replace */
452 * Sets the selection from the current cursor position to length
453 * characters to the right. No safety checks.
455 void setSelectionRange(lyx::pos_type length);
457 /** simple replacing. The font of the first selected character
460 void replaceSelectionWithString(string const & str);
462 /// needed to insert the selection
463 void insertStringAsLines(string const & str);
464 /// needed to insert the selection
465 void insertStringAsParagraphs(string const & str);
467 /// Find next inset of some specified type.
468 bool gotoNextInset(std::vector<Inset::Code> const & codes,
469 string const & contents = string());
471 void gotoInset(std::vector<Inset::Code> const & codes,
474 void gotoInset(Inset::Code code, bool same_content);
477 /* for the greater insets */
479 /// returns false if inset wasn't found
480 bool updateInset(Inset *);
482 void checkParagraph(Paragraph * par, lyx::pos_type pos);
484 int workWidth() const;
486 int workWidth(Inset * inset) const;
488 void computeBidiTables(Buffer const *, Row * row) const;
490 /// Maps positions in the visual string to positions in logical string.
492 lyx::pos_type log2vis(lyx::pos_type pos) const {
493 if (bidi_start == -1)
496 return log2vis_list[pos-bidi_start];
499 /// Maps positions in the logical string to positions in visual string.
501 lyx::pos_type vis2log(lyx::pos_type pos) const {
502 if (bidi_start == -1)
505 return vis2log_list[pos-bidi_start];
509 lyx::pos_type bidi_level(lyx::pos_type pos) const {
510 if (bidi_start == -1)
513 return bidi_levels[pos-bidi_start];
517 bool bidi_InRange(lyx::pos_type pos) const {
518 return bidi_start == -1 ||
519 (bidi_start <= pos && pos <= bidi_end);
528 void cursorLeftOneWord(LyXCursor &);
531 float getCursorX(Row *, lyx::pos_type pos,
532 lyx::pos_type last, bool boundary) const;
533 /// used in setlayout
534 void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
536 /** forces the redrawing of a paragraph. Needed when manipulating a
539 void redoDrawingOfParagraph(LyXCursor const & cursor);
541 /** Copybuffer for copy environment type.
542 Asger has learned that this should be a buffer-property instead
543 Lgb has learned that 'char' is a lousy type for non-characters
545 string copylayouttype;
547 /** inserts a new row behind the specified row, increments
548 the touched counters */
549 void insertRow(Row * row, Paragraph * par, lyx::pos_type pos);
550 /// removes the row and reset the touched counters
551 void removeRow(Row * row);
553 /// remove all following rows of the paragraph of the specified row.
554 void removeParagraph(Row * row);
556 /// insert the specified paragraph behind the specified row
557 void insertParagraph(Paragraph * par, Row * row);
559 /** appends the implizit specified paragraph behind the specified row,
560 * start at the implizit given position */
561 void appendParagraph(Row * row);
564 void breakAgain(Row * row);
565 /// Calculate and set the height of the row
566 void setHeightOfRow(Row * row_ptr);
568 // fix the cursor `cur' after a characters has been deleted at `where'
569 // position. Called by deleteEmptyParagraphMechanism
570 void fixCursorAfterDelete(LyXCursor & cur,
571 LyXCursor const & where);
573 /// delete double space (false) or empty paragraphs (true) around old_cursor
574 bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor);
577 /** Updates all counters starting BEHIND the row. Changed paragraphs
578 * with a dynamic left margin will be rebroken. */
579 void updateCounters();
581 void update(bool changed = true);
583 * Returns an inset if inset was hit, or 0 if not.
584 * If hit, the coordinates are changed relative to the inset.
586 Inset * checkInsetHit(int & x, int & y);
589 int singleWidth(Paragraph * par,
590 lyx::pos_type pos) const;
592 int singleWidth(Paragraph * par,
593 lyx::pos_type pos, char c) const;
595 /// return the color of the canvas
596 LColor::color backgroundColor() const;
599 mutable bool bidi_same_direction;
601 unsigned char transformChar(unsigned char c, Paragraph * par,
602 lyx::pos_type pos) const;
605 * Returns the left beginning of the text.
606 * This information cannot be taken from the layout object, because
607 * in LaTeX the beginning of the text fits in some cases
608 * (for example sections) exactly the label-width.
610 int leftMargin(Row const * row) const;
612 int rightMargin(Buffer const &, Row const & row) const;
614 /** this calculates the specified parameters. needed when setting
615 * the cursor and when creating a visible row */
616 void prepareToPrint(Row * row, float & x,
617 float & fill_separator,
619 float & fill_label_hfill,
620 bool bidi = true) const;
624 void setCounter(Buffer const *, Paragraph * par);
626 void deleteWordForward();
628 void deleteWordBackward();
630 void deleteLineForward();
633 * some low level functions
637 /// return the pos value *before* which a row should break.
638 /// for example, the pos at which IsNewLine(pos) == true
639 lyx::pos_type rowBreakPoint(Row const & row) const;
641 /// returns the minimum space a row needs on the screen in pixel
642 int fill(Row & row, int workwidth) const;
645 * returns the minimum space a manual label needs on the
648 int labelFill(Row const & row) const;
651 int labelEnd(Row const & row) const;
654 mutable std::vector<lyx::pos_type> log2vis_list;
657 mutable std::vector<lyx::pos_type> vis2log_list;
660 mutable std::vector<lyx::pos_type> bidi_levels;
663 mutable lyx::pos_type bidi_start;
666 mutable lyx::pos_type bidi_end;
672 // special owner functions
674 Paragraph * ownerParagraph() const;
676 void ownerParagraph(Paragraph *) const;
677 // set it searching first for the right owner using the paragraph id
678 void ownerParagraph(int id, Paragraph *) const;
680 /// return true if this is owned by an inset.
681 bool isInInset() const;
684 /// return the default height of a row in pixels, considering font zoom
685 extern int defaultRowHeight();