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
43 /// the refresh_row needs repainting
44 NEED_VERY_LITTLE_REFRESH = 1,
45 /// everything from refresh_y downwards needs repainting
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
67 LyXText(BufferView *, InsetText *);
72 void init(BufferView *, bool reinit = false);
77 /// the current font settings
80 LyXFont real_current_font;
82 /** the 'anchor' row: the position of this row remains constant
83 * with respect to the top of the screen
86 /** the pixel offset with respect to this row of top_y
88 int anchor_row_offset_;
90 /// get the y coord. of the top of the screen (relative to doc start)
92 /// set the y coord. of the top of the screen (relative to doc start)
94 /// set the anchoring row. top_y will be computed relative to this
95 void anchor_row(Row * row);
97 InsetText * inset_owner;
99 UpdatableInset * the_locking_inset;
102 int getRealCursorX() const;
104 LyXFont const getFont(Buffer const *, Paragraph * par,
105 lyx::pos_type pos) const;
107 LyXFont const getLayoutFont(Buffer const *, Paragraph * par) const;
109 LyXFont const getLabelFont(Buffer const *, Paragraph * par) const;
111 void setCharFont(Buffer const *, Paragraph * par,
112 lyx::pos_type pos, LyXFont const & font);
113 void setCharFont(Paragraph * par,
114 lyx::pos_type pos, LyXFont const & font, bool toggleall);
117 void breakAgainOneRow(Row * row);
118 /// what you expect when pressing <enter> at cursor position
119 void breakParagraph(ParagraphList & paragraphs, char keep_layout = 0);
121 /** set layout over selection and make a total rebreak of
124 Paragraph * setLayout(LyXCursor & actual_cursor,
125 LyXCursor & selection_start,
126 LyXCursor & selection_end,
127 string const & layout);
129 void setLayout(string const & layout);
131 /** increment depth over selection and make a total rebreak of those
136 /** decrement depth over selection and make a total rebreak of those
140 /// get the depth at current cursor position
141 int getDepth() const;
143 /** set font over selection and make a total rebreak of those
145 toggleall defaults to false.
147 void setFont(LyXFont const &, bool toggleall = false);
149 /** deletes and inserts again all paragaphs between the cursor
150 and the specified par. The Cursor is needed to set the refreshing
152 This function is needed after SetLayout and SetFont etc.
154 void redoParagraphs(LyXCursor const & cursor,
155 Paragraph const * end_par);
157 void redoParagraph();
160 void toggleFree(LyXFont const &, bool toggleall = false);
163 string getStringToIndex();
165 /** recalculates the heights of all previous rows of the
166 specified paragraph. needed, if the last characters font
169 void redoHeightOfParagraph();
171 /** insert a character, moves all the following breaks in the
172 same Paragraph one to the right and make a little rebreak
174 void insertChar(char c);
176 void insertInset(Inset * inset);
178 /// Completes the insertion with a full rebreak
182 Row * need_break_row;
184 /// clear any pending paints
188 * Mark position y as the starting point for a repaint
190 void postPaint(int start_y);
193 * Mark the given row at position y as needing a repaint.
195 void postRowPaint(Row * row, int start_y);
198 Inset::RESULT dispatch(FuncRequest const & cmd);
202 BufferView * bv() const;
204 friend class LyXScreen;
207 * Return the status. This represents what repaints are
208 * pending after some operation (e.g. inserting a char).
210 text_status status() const;
214 * The pixel y position from which to repaint the screen.
215 * The position is absolute along the height of outermost
216 * lyxtext (I think). NEED_MORE_REFRESH and NEED_LITTLE_REFRESH
217 * repaints both use this as a starting point (if it's within
218 * the viewable portion of the lyxtext).
222 * The row from which to repaint the screen, used by screen.c.
223 * This must be set if the pending update is NEED_LITTLE_REFRESH.
224 * It doesn't make any difference for NEED_MORE_REFRESH.
231 /// only the top-level LyXText has this non-zero
232 BufferView * bv_owner;
235 /** returns a pointer to the row near the specified y-coordinate
236 (relative to the whole text). y is set to the real beginning
239 Row * getRowNearY(int & y) const;
241 /** returns the column near the specified x-coordinate of the row
242 x is set to the real beginning of this column
244 lyx::pos_type getColumnNearX(Row * row,
245 int & x, bool & boundary) const;
247 /** returns a pointer to a specified row. y is set to the beginning
250 Row * getRow(Paragraph * par, lyx::pos_type pos, int & y) const;
251 /** returns the firstrow, this could be done with the above too but
252 IMO it's stupid to have to allocate a dummy y all the time I need
255 Row * firstRow() const { return firstrow; }
258 Later this variable has to be removed. There should be now internal
259 cursor in a text (and thus not in a buffer). By keeping this it is
260 (I think) impossible to have several views with the same buffer, but
261 the cursor placed at different places.
263 Since the LyXText now has been moved from Buffer to BufferView
264 it should not be absolutely needed to move the cursor...
266 LyXCursor cursor; // actual cursor position
268 /** The structure that keeps track of the selections set. */
271 : set_(false), mark_(false)
285 LyXCursor cursor; // temporary cursor to hold a cursor position
286 // until setSelection is called!
287 LyXCursor start; // start of a REAL selection
288 LyXCursor end; // end of a REAL selection
290 bool set_; // former selection
291 bool mark_; // former mark_set
295 // this is used to handle XSelection events in the right manner
296 Selection xsel_cache;
298 /// needed for the toggling (cursor position on last selection made)
299 LyXCursor last_sel_cursor;
300 /// needed for toggling the selection in screen.C
301 LyXCursor toggle_cursor;
302 /// needed for toggling the selection in screen.C
303 LyXCursor toggle_end_cursor;
305 /// need the selection cursor:
308 void clearSelection();
310 string const selectionAsString(Buffer const *, bool label) const;
312 /// select the word we need depending on word_location
313 void getWord(LyXCursor & from, LyXCursor & to,
314 word_location const);
315 /// just selects the word the cursor is in
316 void selectWord(word_location const);
317 /// returns the inset at cursor (if it exists), 0 otherwise
318 Inset * getInset() const;
320 /// accept selected change
323 /// reject selected change
326 /** 'selects" the next word, where the cursor is not in
327 and returns this word as string. THe cursor will be moved
328 to the beginning of this word.
329 With SelectSelectedWord can this be highlighted really
331 WordLangTuple const selectNextWordToSpellcheck(float & value);
333 void selectSelectedWord();
334 /// returns true if par was empty and was removed
335 bool setCursor(Paragraph * par,
338 bool boundary = false);
340 void setCursor(LyXCursor &, Paragraph * par,
342 bool boundary = false);
344 void setCursorIntern(Paragraph * par,
347 bool boundary = false);
349 void setCurrentFont();
352 bool isBoundary(Buffer const *, Paragraph * par,
353 lyx::pos_type pos) const;
355 bool isBoundary(Buffer const *, Paragraph * par,
357 LyXFont const & font) const;
360 void setCursorFromCoordinates(int x, int y);
362 void setCursorFromCoordinates(LyXCursor &,
365 void cursorUp(bool selecting = false);
367 void cursorDown(bool selecting = false);
369 void cursorLeft(bool internal = true);
371 void cursorRight(bool internal = true);
373 void cursorLeftOneWord();
375 void cursorRightOneWord();
377 void cursorUpParagraph();
379 void cursorDownParagraph();
385 void cursorPrevious();
399 bool selectWordWhenUnderCursor(word_location);
405 text_capitalization = 1,
409 /// Change the case of the word at cursor position.
410 void changeCase(TextCase action);
412 void transposeChars();
417 void cutSelection(bool doclear = true, bool realcut = true);
419 void copySelection();
421 void pasteSelection();
423 void copyEnvironmentType();
425 void pasteEnvironmentType();
427 /** the DTP switches for paragraphs. LyX will store the top settings
428 always in the first physical paragraph, the bottom settings in the
429 last. When a paragraph is broken, the top settings rest, the bottom
430 settings are given to the new one. So I can make shure, they do not
431 duplicate themself (and you cannnot make dirty things with them! )
433 void setParagraph(bool line_top, bool line_bottom,
434 bool pagebreak_top, bool pagebreak_bottom,
435 VSpace const & space_top,
436 VSpace const & space_bottom,
437 Spacing const & spacing,
439 string const & labelwidthstring,
442 /* these things are for search and replace */
445 * Sets the selection from the current cursor position to length
446 * characters to the right. No safety checks.
448 void setSelectionRange(lyx::pos_type length);
450 /** simple replacing. The font of the first selected character
453 void replaceSelectionWithString(string const & str);
455 /// needed to insert the selection
456 void insertStringAsLines(string const & str);
457 /// needed to insert the selection
458 void insertStringAsParagraphs(string const & str);
460 /// Find next inset of some specified type.
461 bool gotoNextInset(std::vector<Inset::Code> const & codes,
462 string const & contents = string());
464 void gotoInset(std::vector<Inset::Code> const & codes,
467 void gotoInset(Inset::Code code, bool same_content);
470 /* for the greater insets */
472 /// returns false if inset wasn't found
473 bool updateInset(Inset *);
475 void checkParagraph(Paragraph * par, lyx::pos_type pos);
477 int workWidth() const;
479 int workWidth(Inset * inset) const;
482 void computeBidiTables(Buffer const *, Row * row) const;
483 /// Maps positions in the visual string to positions in logical string.
484 lyx::pos_type log2vis(lyx::pos_type pos) const;
485 /// Maps positions in the logical string to positions in visual string.
486 lyx::pos_type vis2log(lyx::pos_type pos) const;
488 lyx::pos_type bidi_level(lyx::pos_type pos) const;
490 bool bidi_InRange(lyx::pos_type pos) const;
498 void cursorLeftOneWord(LyXCursor &);
501 float getCursorX(Row *, lyx::pos_type pos,
502 lyx::pos_type last, bool boundary) const;
503 /// used in setlayout
504 void makeFontEntriesLayoutSpecific(Buffer const &, Paragraph & par);
506 /** forces the redrawing of a paragraph. Needed when manipulating a
509 void redoDrawingOfParagraph(LyXCursor const & cursor);
511 /** Copybuffer for copy environment type.
512 Asger has learned that this should be a buffer-property instead
513 Lgb has learned that 'char' is a lousy type for non-characters
515 string copylayouttype;
517 /** inserts a new row behind the specified row, increments
518 the touched counters */
519 void insertRow(Row * row, Paragraph * par, lyx::pos_type pos);
520 /// removes the row and reset the touched counters
521 void removeRow(Row * row);
523 /// remove all following rows of the paragraph of the specified row.
524 void removeParagraph(Row * row);
526 /// insert the specified paragraph behind the specified row
527 void insertParagraph(Paragraph * par, Row * row);
529 /** appends the implizit specified paragraph behind the specified row,
530 * start at the implizit given position */
531 void appendParagraph(Row * row);
534 void breakAgain(Row * row);
535 /// Calculate and set the height of the row
536 void setHeightOfRow(Row * row_ptr);
538 // fix the cursor `cur' after a characters has been deleted at `where'
539 // position. Called by deleteEmptyParagraphMechanism
540 void fixCursorAfterDelete(LyXCursor & cur,
541 LyXCursor const & where);
543 /// delete double space (false) or empty paragraphs (true) around old_cursor
544 bool deleteEmptyParagraphMechanism(LyXCursor const & old_cursor);
547 /** Updates all counters starting BEHIND the row. Changed paragraphs
548 * with a dynamic left margin will be rebroken. */
549 void updateCounters();
553 * Returns an inset if inset was hit, or 0 if not.
554 * If hit, the coordinates are changed relative to the inset.
556 Inset * checkInsetHit(int & x, int & y);
559 int singleWidth(Paragraph * par,
560 lyx::pos_type pos) const;
562 int singleWidth(Paragraph * par,
563 lyx::pos_type pos, char c) const;
565 /// return the color of the canvas
566 LColor::color backgroundColor() const;
569 mutable bool bidi_same_direction;
571 unsigned char transformChar(unsigned char c, Paragraph * par,
572 lyx::pos_type pos) const;
575 * Returns the left beginning of the text.
576 * This information cannot be taken from the layout object, because
577 * in LaTeX the beginning of the text fits in some cases
578 * (for example sections) exactly the label-width.
580 int leftMargin(Row const * row) const;
582 int rightMargin(Buffer const &, Row const & row) const;
584 /** this calculates the specified parameters. needed when setting
585 * the cursor and when creating a visible row */
586 void prepareToPrint(Row * row, float & x,
587 float & fill_separator,
589 float & fill_label_hfill,
590 bool bidi = true) const;
594 void setCounter(Buffer const *, Paragraph * par);
596 void deleteWordForward();
598 void deleteWordBackward();
600 void deleteLineForward();
603 * some low level functions
607 /// return the pos value *before* which a row should break.
608 /// for example, the pos at which IsNewLine(pos) == true
609 lyx::pos_type rowBreakPoint(Row const & row) const;
611 /// returns the minimum space a row needs on the screen in pixel
612 int fill(Row & row, int workwidth) const;
615 * returns the minimum space a manual label needs on the
618 int labelFill(Row const & row) const;
621 int labelEnd(Row const & row) const;
624 mutable std::vector<lyx::pos_type> log2vis_list;
626 mutable std::vector<lyx::pos_type> vis2log_list;
628 mutable std::vector<lyx::pos_type> bidi_levels;
630 mutable lyx::pos_type bidi_start;
632 mutable lyx::pos_type bidi_end;
638 // special owner functions
640 Paragraph * ownerParagraph() const;
642 void ownerParagraph(Paragraph *) const;
643 // set it searching first for the right owner using the paragraph id
644 void ownerParagraph(int id, Paragraph *) const;
646 /// return true if this is owned by an inset.
647 bool isInInset() const;
650 /// return the default height of a row in pixels, considering font zoom
651 extern int defaultRowHeight();