mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-24 10:40:48 +00:00
71623b88b2
Now backspace and delete in text will select non-empty math and text insets before deleting them. This is consistent with what happens in math already. This is implemented for InsetText as well but can be disabled in case of negative feedback. This can be set for any sort of inset with the new virtual method Inset::confirmDeletion. New option "force" for the LFUN_*_DELETE_* commands, that bypasses the confirmDeletion check.
411 lines
14 KiB
C++
411 lines
14 KiB
C++
// -*- C++ -*-
|
|
/**
|
|
* \file Text.h
|
|
* This file is part of LyX, the document processor.
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* \author unknown
|
|
* \author Lars Gullik Bjønnes
|
|
* \author John Levon
|
|
*
|
|
* Full author contact details are available in file CREDITS.
|
|
*/
|
|
|
|
#ifndef TEXT_H
|
|
#define TEXT_H
|
|
|
|
#include "DocIterator.h"
|
|
#include "ParagraphList.h"
|
|
|
|
namespace lyx {
|
|
|
|
class Buffer;
|
|
class BufferParams;
|
|
class BufferView;
|
|
class CompletionList;
|
|
class Cursor;
|
|
class CursorSlice;
|
|
class DocIterator;
|
|
class ErrorList;
|
|
class Font;
|
|
class FontInfo;
|
|
class FuncRequest;
|
|
class FuncStatus;
|
|
class Inset;
|
|
class Lexer;
|
|
class PainterInfo;
|
|
class Spacing;
|
|
|
|
/// This class encapsulates the main text data and operations in LyX.
|
|
/// This is more or less the private implementation of InsetText.
|
|
class Text {
|
|
private:
|
|
/// Default constructor.
|
|
Text(InsetText * owner, bool use_default_layout);
|
|
|
|
/// Copy constructor.
|
|
Text(InsetText * owner, Text const & text);
|
|
|
|
public:
|
|
/// \return true if there's no content at all.
|
|
/// \warning a non standard layout on an empty paragraph doesn't
|
|
// count as empty.
|
|
bool empty() const;
|
|
/// Access to owner InsetText.
|
|
InsetText const & inset() const;
|
|
|
|
///
|
|
FontInfo layoutFont(pit_type pit) const;
|
|
///
|
|
FontInfo labelFont(Paragraph const & par) const;
|
|
/** Set font of character at position \p pos in paragraph \p pit.
|
|
* Must not be called if \p pos denotes an inset with text contents,
|
|
* and the inset is not allowed inside a font change (see below).
|
|
*/
|
|
void setCharFont(pit_type pit, pos_type pos,
|
|
Font const & font, Font const & display_font);
|
|
|
|
/** Needed to propagate font changes to all text cells of insets
|
|
* that are not allowed inside a font change (bugs 1973, 6919).
|
|
* Must not be called if \p pos denotes an ordinary character or an
|
|
* inset that is alowed inside a font change.
|
|
*/
|
|
void setInsetFont(BufferView const & bv, pit_type pit, pos_type pos,
|
|
Font const & font);
|
|
|
|
/// what you expect when pressing \<enter\> at cursor position
|
|
/// \param inverse_logic if false, the same layout is set for the
|
|
/// new paragraph if the layout is an environment; if true, the
|
|
/// same layout is set if it is not an environment
|
|
void breakParagraph(Cursor & cur, bool inverse_logic = false);
|
|
|
|
/// set layout over selection
|
|
void setLayout(pit_type start, pit_type end,
|
|
docstring const & layout);
|
|
/// Set given layout to current cursor position or selection.
|
|
/// Handles undo.
|
|
void setLayout(Cursor & cur, docstring const & layout);
|
|
|
|
/// what type of depth change to make
|
|
enum DEPTH_CHANGE {
|
|
INC_DEPTH,
|
|
DEC_DEPTH
|
|
};
|
|
/// Increase or decrease the nesting depth of the selected paragraph(s)
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
void changeDepth(Cursor & cur, DEPTH_CHANGE type);
|
|
|
|
/// Returns whether something would be changed by changeDepth
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
bool changeDepthAllowed(Cursor & cur, DEPTH_CHANGE type) const;
|
|
|
|
/// Set font over selection paragraphs and rebreak.
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
void setFont(Cursor & cur, Font const &, bool toggleall = false);
|
|
/// Set font from \p begin to \p end and rebreak.
|
|
void setFont(BufferView const & bv, CursorSlice const & begin,
|
|
CursorSlice const & end, Font const &);
|
|
|
|
///
|
|
void toggleFree(Cursor & cur, Font const &, bool toggleall = false);
|
|
|
|
/// ???
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
docstring getStringToIndex(Cursor const & cur);
|
|
|
|
/// Convert the paragraphs to a string.
|
|
/// \param AsStringParameter options. This can contain any combination of
|
|
/// asStringParameter values. Valid examples:
|
|
/// asString(AS_STR_LABEL)
|
|
/// asString(AS_STR_LABEL | AS_STR_INSETS)
|
|
/// asString(AS_STR_INSETS)
|
|
docstring asString(int options = AS_STR_NONE) const;
|
|
///
|
|
docstring asString(pit_type beg, pit_type end,
|
|
int options = AS_STR_NONE) const;
|
|
|
|
/// truncates str to maxlenwith an ellipsis and replaces the characters '\n'
|
|
/// and '\t' with spaces
|
|
static void shortenForOutliner(docstring & str, size_t const maxlen);
|
|
|
|
/// Appends a possibly abbreviated representation of our text to \param os,
|
|
/// where \param maxlen defines the maximum size of \param os. If \param
|
|
/// shorten is true, then os is shortened as above.
|
|
void forOutliner(docstring & os, size_t maxlen, bool shorten = true) const;
|
|
/// Appends a possibly abbreviated representation of our text, from
|
|
/// start to end, to \param os, where \param maxlen defines the
|
|
/// maximum size of \param os. Omits the label of the first paragraph.
|
|
void forOutliner(docstring & os, size_t maxlen, pit_type start, pit_type end,
|
|
bool shorten = true) const;
|
|
|
|
/// insert a character at cursor position
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
void insertChar(Cursor & cur, char_type c);
|
|
/// insert an inset at cursor position
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
void insertInset(Cursor & cur, Inset * inset);
|
|
|
|
/// try to handle that request
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
void dispatch(Cursor & cur, FuncRequest & cmd);
|
|
/// do we want to handle this event?
|
|
bool getStatus(Cursor & cur, FuncRequest const & cmd,
|
|
FuncStatus & status) const;
|
|
|
|
/// read-only access to individual paragraph
|
|
Paragraph const & getPar(pit_type pit) const { return pars_[pit]; }
|
|
/// read-write access to individual paragraph
|
|
Paragraph & getPar(pit_type pit) { return pars_[pit]; }
|
|
// Returns the current font and depth as a message.
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
docstring currentState(Cursor const & cur) const;
|
|
|
|
/** Find the word under \c from in the relative location
|
|
* defined by \c word_location.
|
|
* @param from return here the start of the word
|
|
* @param to return here the end of the word
|
|
*/
|
|
void getWord(CursorSlice & from, CursorSlice & to, word_location const) const;
|
|
/// just selects the word the cursor is in
|
|
void selectWord(Cursor & cur, word_location loc);
|
|
/// select all text
|
|
void selectAll(Cursor & cur);
|
|
/// convenience function get the previous word or an empty string
|
|
docstring previousWord(CursorSlice const & sl) const;
|
|
|
|
/// what type of change operation to make
|
|
enum ChangeOp {
|
|
ACCEPT,
|
|
REJECT
|
|
};
|
|
/// accept or reject the selected change
|
|
void acceptOrRejectChanges(Cursor & cur, ChangeOp op);
|
|
/// accept the changes within the complete Text
|
|
void acceptChanges();
|
|
/// reject the changes within the complete Text
|
|
void rejectChanges();
|
|
|
|
/// returns true if par was empty and was removed
|
|
bool setCursor(Cursor & cur, pit_type pit, pos_type pos,
|
|
bool setfont = true, bool boundary = false);
|
|
///
|
|
void setCursorIntern(Cursor & cur, pit_type pit,
|
|
pos_type pos, bool setfont = true, bool boundary = false);
|
|
|
|
/// Move cursor one position backwards
|
|
/**
|
|
* Returns true if an update is needed after the move.
|
|
*/
|
|
bool cursorBackward(Cursor & cur);
|
|
/// Move cursor visually one position to the left
|
|
/**
|
|
* \param skip_inset if true, don't enter insets
|
|
* Returns true if an update is needed after the move.
|
|
*/
|
|
bool cursorVisLeft(Cursor & cur, bool skip_inset = false);
|
|
/// Move cursor one position forward
|
|
/**
|
|
* Returns true if an update is needed after the move.
|
|
*/
|
|
bool cursorForward(Cursor & cur);
|
|
/// Move cursor visually one position to the right
|
|
/**
|
|
* \param skip_inset if true, don't enter insets
|
|
* Returns true if an update is needed after the move.
|
|
*/
|
|
bool cursorVisRight(Cursor & cur, bool skip_inset = false);
|
|
///
|
|
bool cursorBackwardOneWord(Cursor & cur);
|
|
///
|
|
bool cursorForwardOneWord(Cursor & cur);
|
|
///
|
|
bool cursorVisLeftOneWord(Cursor & cur);
|
|
///
|
|
bool cursorVisRightOneWord(Cursor & cur);
|
|
/// Delete from cursor up to the end of the current or next word.
|
|
/// Use force to skip the confirmDeletion check.
|
|
void deleteWordForward(Cursor & cur, bool force = false);
|
|
/// Delete from cursor to start of current or prior word.
|
|
void deleteWordBackward(Cursor & cur, bool force = false);
|
|
///
|
|
bool cursorUpParagraph(Cursor & cur);
|
|
///
|
|
bool cursorDownParagraph(Cursor & cur);
|
|
///
|
|
bool cursorTop(Cursor & cur);
|
|
///
|
|
bool cursorBottom(Cursor & cur);
|
|
/// Erase character at cursor. Honour change tracking
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
bool erase(Cursor & cur);
|
|
/// Delete character before cursor. Honour CT
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
bool backspace(Cursor & cur);
|
|
// Dissolve the inset under cursor
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
bool dissolveInset(Cursor & cur);
|
|
///
|
|
bool selectWordWhenUnderCursor(Cursor & cur, word_location);
|
|
/// Change the case of the word at cursor position.
|
|
void changeCase(Cursor & cur, TextCase action, bool partial);
|
|
/// Transposes the character at the cursor with the one before it
|
|
void charsTranspose(Cursor & cur);
|
|
|
|
/** the DTP switches for paragraphs. LyX will store the top settings
|
|
always in the first physical paragraph, the bottom settings in the
|
|
last. When a paragraph is broken, the top settings rest, the bottom
|
|
settings are given to the new one.
|
|
This function will handle a multi-paragraph selection.
|
|
*/
|
|
void setParagraphs(Cursor & cur, docstring arg, bool modify = false);
|
|
/// Sets parameters for current or selected paragraphs
|
|
void setParagraphs(Cursor & cur, ParagraphParameters const & p);
|
|
|
|
/* these things are for search and replace */
|
|
|
|
/// needed to insert the selection
|
|
void insertStringAsLines(Cursor & cur, docstring const & str,
|
|
Font const & font);
|
|
/// needed to insert the selection
|
|
void insertStringAsParagraphs(Cursor & cur, docstring const & str,
|
|
Font const & font);
|
|
|
|
/// access to our paragraphs
|
|
ParagraphList const & paragraphs() const { return pars_; }
|
|
ParagraphList & paragraphs() { return pars_; }
|
|
/// return true if this is the main text
|
|
bool isMainText() const;
|
|
|
|
///
|
|
double spacing(Paragraph const & par) const;
|
|
/// make a suggestion for a label
|
|
/// FIXME: replace Cursor with DocIterator.
|
|
docstring getPossibleLabel(Cursor const & cur) const;
|
|
/// is this paragraph right-to-left?
|
|
bool isRTL(Paragraph const & par) const;
|
|
|
|
///
|
|
bool checkAndActivateInset(Cursor & cur, bool front);
|
|
///
|
|
bool checkAndActivateInsetVisual(Cursor & cur, bool movingForward, bool movingLeft);
|
|
|
|
///
|
|
void write(std::ostream & os) const;
|
|
/// returns true if \end_document has not been read
|
|
/// insetPtr is the containing Inset
|
|
bool read(Lexer & lex, ErrorList & errorList,
|
|
InsetText * insetPtr);
|
|
|
|
/// delete double spaces, leading spaces, and empty paragraphs around old cursor.
|
|
/// \retval true if a change has happened and we need a redraw.
|
|
/// FIXME: replace Cursor with DocIterator. This is not possible right
|
|
/// now because recordUndo() is called which needs a Cursor.
|
|
static bool deleteEmptyParagraphMechanism(Cursor & cur,
|
|
Cursor & old, bool & need_anchor_change);
|
|
|
|
/// delete double spaces, leading spaces, and empty paragraphs
|
|
/// from \first to \last paragraph
|
|
void deleteEmptyParagraphMechanism(pit_type first, pit_type last, bool trackChanges);
|
|
|
|
/// To resolve macros properly the texts get their DocIterator.
|
|
/// Every macro definition is stored with its DocIterator
|
|
/// as well. Only those macros with a smaller iterator become
|
|
/// visible in a paragraph.
|
|
DocIterator macrocontextPosition() const;
|
|
///
|
|
void setMacrocontextPosition(DocIterator const & pos);
|
|
|
|
///
|
|
bool completionSupported(Cursor const & cur) const;
|
|
///
|
|
CompletionList const * createCompletionList(Cursor const & cur) const;
|
|
///
|
|
bool insertCompletion(Cursor & cur, docstring const & s, bool /*finished*/);
|
|
///
|
|
docstring completionPrefix(Cursor const & cur) const;
|
|
/// find a paragraph before \p par with the given \p depth, if such
|
|
/// a paragraph cannot be found, \p par is returned
|
|
pit_type depthHook(pit_type pit, depth_type depth) const;
|
|
/// find a paragraph before \p par with depth less than the
|
|
/// depth of \p par. If such paragraph cannot be found because
|
|
/// \p par already has depth 0, lastpar + 1 is returned. If
|
|
/// such paragraph cannot be found because there isn't a par
|
|
/// with less depth before this one, \p par is returned.
|
|
pit_type outerHook(pit_type pit) const;
|
|
/// Is it the first par with same depth and layout?
|
|
bool isFirstInSequence(pit_type pit) const;
|
|
/// Return the last paragraph with same depth and layout, or a strictly
|
|
/// greater depth
|
|
pit_type lastInSequence(pit_type pit) const;
|
|
/// Is this paragraph in the table of contents?
|
|
int getTocLevel(pit_type pit) const;
|
|
/// Get the font of the "environment" of paragraph \p par_offset in \p pars.
|
|
/// All font changes of the paragraph are relative to this font.
|
|
Font const outerFont(pit_type pit_offset) const;
|
|
|
|
private:
|
|
/// The InsetText owner shall have access to everything.
|
|
friend class InsetText;
|
|
|
|
// fix the cursor `cur' after a characters has been deleted at `where'
|
|
// position. Called by deleteEmptyParagraphMechanism
|
|
static void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where);
|
|
|
|
// At cursor position 0, try to merge the paragraph with the one before it.
|
|
// Ignore change tracking, i.e., physically remove the end-of-par character
|
|
bool backspacePos0(Cursor & cur);
|
|
/// handle the case where bibitems were deleted
|
|
bool handleBibitems(Cursor & cur);
|
|
/// are we in a list item (description etc.)?
|
|
bool inDescriptionItem(Cursor & cur) const;
|
|
///
|
|
void charInserted(Cursor & cur);
|
|
/// set 'number' font property
|
|
void number(Cursor & cur);
|
|
|
|
/// paste plain text at current cursor.
|
|
/// \param str string to paste
|
|
/// \param asParagraphs whether to paste as paragraphs or as lines
|
|
void pasteString(Cursor & cur, docstring const & str,
|
|
bool asParagraphs);
|
|
///
|
|
void readParToken(Paragraph & par, Lexer & lex, std::string const & token,
|
|
Font & font, Change & change, ErrorList & errorList);
|
|
///
|
|
void readParagraph(Paragraph & par, Lexer & lex, ErrorList & errorList);
|
|
/// Set Label Width string to all paragraphs of the same layout
|
|
/// and depth in a sequence.
|
|
void setLabelWidthStringToSequence(Cursor const & cur, docstring const & s);
|
|
|
|
/// Owner Inset.
|
|
InsetText * owner_;
|
|
///
|
|
ParagraphList pars_;
|
|
/// position of the text in the buffer.
|
|
DocIterator macrocontext_position_;
|
|
};
|
|
|
|
|
|
///
|
|
void breakParagraphConservative(BufferParams const & bparams,
|
|
ParagraphList & paragraphs,
|
|
pit_type pit,
|
|
pos_type pos);
|
|
|
|
/**
|
|
* Append the next paragraph onto the tail of this one.
|
|
* Be careful, this doesent make any check at all.
|
|
*/
|
|
void mergeParagraph(BufferParams const & bparams,
|
|
ParagraphList & paragraphs, pit_type pit);
|
|
|
|
/// accept the changes within the complete ParagraphList
|
|
void acceptChanges(ParagraphList & pars, BufferParams const & bparams);
|
|
|
|
/// reject the changes within the complete ParagraphList
|
|
void rejectChanges(ParagraphList & pars, BufferParams const & bparams);
|
|
|
|
} // namespace lyx
|
|
|
|
#endif // TEXT_H
|