lyx_mirror/src/Text.h

408 lines
14 KiB
C
Raw Normal View History

// -*- 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;
This commit creates a error_lists map member inside the Buffer class. I had no choice but to use string for the map key. This is because the only information that could be passed to the controller is a string. With this new architecture, persistent error lists are now possible. * Buffer - errorList_, addError(), : deleted - std::map<std::string, ErrorList> errorLists_ : new member - errorList(std::string const & type): associated accessors * buffer_funcs.C - bufferErrors(Buffer const & buf, TeXErrors const & terr): now needs a third errorList argument - bufferErrors(Buffer const & buf, ErrorList const & el): deleted. * Converter - convert(): now needs an ErrorList argument instead of filling the Buffer errorList member directly. - runLaTeX(): ditto - scanLog(): ditto * CutAndPaste.C - pasteParagraphList(): ditto - pasteSelection(): ditto * lyxtext.h/text.C - readParagraph(): ditto - LyXText::read(): ditto * importer: - Importer::Import(): ditto * BufferView_pimpl.C - loadLyXFile(): send the Buffer::errors() signal instead of calling LyXView::showErrorList() directly. * exporter.C - Export(): send the Buffer::errors() signal instead of calling LyXView::showErrorList() directly in lyxfunc.C * ControlErrorList.C - initialiseParams(): translation operation transfered here from LyXView::showErrorList(). * LyXView.C - LoadLyXFile(): add a showErrorList("Parse") call. - showErrorList(): simplified due to code transferred to the ControlErrorList. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@14652 a592a061-630c-0410-9148-cb99ea01b6c8
2006-08-13 16:16:43 +00:00
class ErrorList;
class Font;
class FontInfo;
class FuncRequest;
class FuncStatus;
class Inset;
class Lexer;
class PainterInfo;
class Spacing;
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
/// 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, bool toggleall = false);
/// 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);
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
/// set layout over selection
void setLayout(pit_type start, pit_type end,
docstring const & layout);
/// Set given layout to current cursor position.
/// FIXME: replace Cursor with DocIterator.
void setLayout(Cursor & cur, docstring const & layout);
/// what type of depth change to make
enum DEPTH_CHANGE {
INC_DEPTH,
DEC_DEPTH
};
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
/// 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 &,
bool toggleall = false);
///
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;
/// 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 we will shorten
/// \param os to maxlen chars and replace the final three by "...,
/// if \param os is longer than maxlen chars.
void forToc(docstring & os, size_t maxlen, 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 par, pos_type pos,
bool setfont = true, bool boundary = false);
///
void setCursor(CursorSlice &, pit_type par, pos_type pos);
///
void setCursorIntern(Cursor & cur, pit_type par,
pos_type pos, bool setfont = true, bool boundary = false);
///
void recUndo(Cursor & cur, pit_type first, pit_type last) const;
///
void recUndo(Cursor & cur, pit_type first) const;
/// 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.
void deleteWordForward(Cursor & cur);
/// Delete from cursor to start of current or prior word.
void deleteWordBackward(Cursor & cur);
///
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);
/// 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
It used to be that things like InsetFlex, InsetCaption, and the like used the default layout, whatever that is---usually Standard. That gave rise to bug 2178, the solution to which is to define a new empty layout, which insets like these use instead of the default. See r22966. So, when we have an older LyX file, it will look like this: \begin_inset ERT status open \begin_layout Standard this that \end_layout \end_inset which is now invalid, because ERT uses only PlainLayout. So I had put some code into Text::readParToken, where the layout for a paragraph gets set as it is read: if (par.forceEmptyLayout()) { // in this case only the empty layout is allowed layoutname = tclass.emptyLayoutName(); } else if (par.useEmptyLayout()) { // in this case, default layout maps to empty layout if (layoutname == tclass.defaultLayoutName()) layoutname = tclass.emptyLayoutName(); } else { // otherwise, the empty layout maps to the default if (layoutname == tclass.emptyLayoutName()) layoutname = tclass.defaultLayoutName(); } This turns out not to work, because par.forceEmptyLayout() and par.useEmptyLayout() always return false here, because par.inInset() always returns a null pointer, because the paragraph's inset hasn't yet been set when Text::readParagraph() gets called from Text::read() gets called from InsetText::read(). The solution is to set the paragraph's inset when it is created, which means passing a pointer to the various read() routines along the way. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@23057 a592a061-630c-0410-9148-cb99ea01b6c8
2008-02-19 02:35:07 +00:00
/// 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;
/// for the environments
pit_type depthHook(pit_type par, depth_type depth) const;
///
pit_type outerHook(pit_type par) const;
/// Is it the first par with same depth and layout?
bool isFirstInSequence(pit_type par) 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 par_offset) const;
private:
/// The InsetText owner shall have access to everything.
friend class InsetText;
/// return past-the-last paragraph influenced by a layout
/// change on pit
pit_type undoSpan(pit_type pit);
// 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(pit_type const par_offset, docstring const & s);
/// Owner Inset.
InsetText * owner_;
///
ParagraphList pars_;
///
bool autoBreakRows_;
/// position of the text in the buffer.
DocIterator macrocontext_position_;
///
unsigned int undo_counter_;
};
///
void breakParagraphConservative(BufferParams const & bparams,
ParagraphList & paragraphs,
pit_type par,
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 par);
/// 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