]> git.lyx.org Git - lyx.git/blobdiff - src/Paragraph.h
Fix text direction issue for InsetInfo in RTL context
[lyx.git] / src / Paragraph.h
index b46960784e2cee6a8a41c7541e9fcd0fbc9e8573..2f61083b801d7c203faae6ffbf25f67740ad6b40 100644 (file)
@@ -5,10 +5,10 @@
  * Licence details can be found in the file COPYING.
  *
  * \author Asger Alstrup
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author John Levon
- * \author André Pönitz
- * \author Jürgen Vigna
+ * \author André Pönitz
+ * \author Jürgen Vigna
  *
  * Full author contact details are available in file CREDITS.
  */
 #ifndef PARAGRAPH_H
 #define PARAGRAPH_H
 
-#include "LayoutPtr.h"
+#include "FontEnums.h"
+#include "LayoutEnums.h"
+#include "SpellChecker.h"
 
-#include "insets/InsetCode.h"
+#include "support/strfwd.h"
+#include "support/types.h"
 
-#include "support/docstring.h"
-// FIXME: would be nice to forward declare odocstream instead of
-// including this:
-#include "support/docstream.h"
-
-#include <vector>
+#include <set>
 
 namespace lyx {
 
@@ -34,20 +32,26 @@ class Buffer;
 class BufferParams;
 class Change;
 class Counters;
+class Cursor;
+class CursorSlice;
+class DocIterator;
+class docstring_list;
+class DocumentClass;
 class Inset;
 class InsetBibitem;
 class LaTeXFeatures;
-class Inset_code;
 class InsetList;
 class Language;
+class Layout;
 class Font;
-class Font_size;
 class MetricsInfo;
 class OutputParams;
 class PainterInfo;
 class ParagraphParameters;
-class TexRow;
-
+class TocBackend;
+class WordLangTuple;
+class XHTMLStream;
+class otexstream;
 
 class FontSpan {
 public:
@@ -59,38 +63,100 @@ public:
 public:
        /// Range including first and last.
        pos_type first, last;
-};
 
+       inline bool operator<(FontSpan const & s) const
+       {
+               return first < s.first;
+       }
+
+       inline bool operator==(FontSpan const & s) const
+       {
+               return first == s.first && last == s.last;
+       }
 
-/// A Paragraph holds all text, attributes and insets in a text paragraph
-/// \todo FIXME: any reference to ParagraphMetrics (including inheritance)
-/// should go in order to complete the Model/View separation of this class.
-class Paragraph  {
-public:
+       inline bool contains(pos_type p) const
+       {
+               return first <= p && p <= last;
+       }
+
+       inline size_t size() const
+       {
+               return empty() ? 0 : last - first;
+       }
+
+
+       inline FontSpan intersect(FontSpan const & f) const
+       {
+               FontSpan result = FontSpan();
+               if (contains(f.first))
+                       result.first = f.first;
+               else if (f.contains(first))
+                       result.first = first;
+               else
+                       return result;
+               if (contains(f.last))
+                       result.last = f.last;
+               else if (f.contains(last))
+                       result.last = last;
+               return result;
+       }
+
+       inline bool empty() const
+       {
+               return first > last;
+       }
+};
+
+///
+enum TextCase {
        ///
-       enum {
-               /// Note that this is 1 right now to avoid
-               /// crashes where getChar() is called wrongly
-               /// (returning 0) - if this was 0, then we'd
-               /// try getInset() and crash. We should fix
-               /// all these places.
-               //META_INSET = 1 // as in trunk
-               META_INSET = 0x200001  // above 0x10ffff, for ucs-4
-       };
+       text_lowercase = 0,
        ///
-       typedef char_type value_type;
+       text_capitalization = 1,
+       ///
+       text_uppercase = 2
+};
+
+
+///
+enum AsStringParameter
+{
+       AS_STR_NONE = 0, ///< No option, only printable characters.
+       AS_STR_LABEL = 1, ///< Prefix with paragraph label.
+       AS_STR_INSETS = 2, ///< Go into insets.
+       AS_STR_NEWLINES = 4, ///< Get also newline characters.
+       AS_STR_SKIPDELETE = 8, ///< Skip deleted text in change tracking.
+       AS_STR_PLAINTEXT = 16 ///< Don't export formatting when descending into insets.
+};
+
 
+/// A Paragraph holds all text, attributes and insets in a text paragraph
+class Paragraph
+{
+public:
        ///
        Paragraph();
-       ///
+       /// Copy constructor.
        Paragraph(Paragraph const &);
+       /// Partial copy constructor.
+       /// Copy the Paragraph contents from \p beg to \p end (without end).
+       Paragraph(Paragraph const & par, pos_type beg, pos_type end);
        ///
        Paragraph & operator=(Paragraph const &);
        ///
        ~Paragraph();
        ///
        int id() const;
+       ///
+       void setId(int id);
 
+       ///
+       void addChangesToToc(DocIterator const & cdit, Buffer const & buf,
+                            bool output_active, TocBackend & backend) const;
+       /// set the buffer flag if there are changes in the paragraph
+       void addChangesToBuffer(Buffer const & buf) const;
+       ///
+       bool isChangeUpdateRequired() const;
        ///
        Language const * getParLanguage(BufferParams const &) const;
        ///
@@ -100,41 +166,48 @@ public:
                            Language const * from, Language const * to);
        ///
        bool isMultiLingual(BufferParams const &) const;
-
        ///
-       docstring const asString(Buffer const &, bool label) const;
+       void getLanguages(std::set<Language const *> &) const;
+
+       /// Convert the paragraph 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;
+
+       /// Convert the paragraph to a string.
+       /// \note If options includes AS_STR_PLAINTEXT, then runparams must be != 0
+       docstring asString(pos_type beg, pos_type end,
+                          int options = AS_STR_NONE,
+                          const OutputParams *runparams = 0) const;
        ///
-       docstring const asString(Buffer const & buffer,
-                                  pos_type beg,
-                                  pos_type end,
-                                  bool label) const;
+       void forOutliner(docstring &, size_t maxlen, bool shorten = true,
+                        bool label = true) const;
 
        ///
-       void write(Buffer const &, std::ostream &, BufferParams const &,
-                  depth_type & depth) const;
+       void write(std::ostream &, BufferParams const &,
+               depth_type & depth) const;
        ///
        void validate(LaTeXFeatures &) const;
 
-       ///
-       bool latex(Buffer const &, BufferParams const &,
-                            Font const & outerfont, odocstream &,
-                            TexRow & texrow, OutputParams const &) const;
+       /// \param force means: output even if layout.inpreamble is true.
+       void latex(BufferParams const &, Font const & outerfont, otexstream &,
+               OutputParams const &, int start_pos = 0, int end_pos = -1,
+               bool force = false) const;
 
        /// Can we drop the standard paragraph wrapper?
        bool emptyTag() const;
 
        /// Get the id of the paragraph, usefull for docbook
-       std::string getID(Buffer const & buf,
-                         OutputParams const & runparams) const;
+       std::string getID(Buffer const & buf, OutputParams const & runparams) const;
 
-       /// Get the first word of a paragraph, return the position where it left
-       pos_type getFirstWord(Buffer const & buf,
-                                  odocstream & os,
-                                  OutputParams const & runparams) const;
+       /// Output the first word of a paragraph, return the position where it left.
+       pos_type firstWordDocBook(odocstream & os, OutputParams const & runparams) const;
 
-       /// Checks if the paragraph contains only text and no inset or font change.
-       bool onlyText(Buffer const & buf, Font const & outerfont,
-                     pos_type initial) const;
+       /// Output the first word of a paragraph, return the position where it left.
+       pos_type firstWordLyXHTML(XHTMLStream & xs, OutputParams const & runparams) const;
 
        /// Writes to stream the docbook representation
        void simpleDocBookOnePar(Buffer const & buf,
@@ -142,6 +215,15 @@ public:
                                 OutputParams const & runparams,
                                 Font const & outerfont,
                                 pos_type initial = 0) const;
+       /// \return any material that has had to be deferred until after the
+       /// paragraph has closed.
+       docstring simpleLyXHTMLOnePar(Buffer const & buf,
+                                XHTMLStream & xs,
+                                OutputParams const & runparams,
+                                Font const & outerfont,
+                                bool start_paragraph = true,
+                                bool close_paragraph = true,
+                                pos_type initial = 0) const;
 
        ///
        bool hasSameLayout(Paragraph const & par) const;
@@ -150,41 +232,49 @@ public:
        void makeSameLayout(Paragraph const & par);
 
        ///
-       void setInsetOwner(Inset * inset);
+       void setInsetOwner(Inset const * inset);
        ///
-       Inset * inInset() const;
+       Inset const & inInset() const;
        ///
-       InsetCode ownerCode() const;
+       bool allowParagraphCustomization() const;
        ///
-       bool forceDefaultParagraphs() const;
-
+       bool usePlainLayout() const;
        ///
-       pos_type size() const { return text_.size(); }
+       bool isPassThru() const;
        ///
-       bool empty() const { return text_.empty(); }
+       pos_type size() const;
+       ///
+       bool empty() const;
 
        ///
-       LayoutPtr const & layout() const;
+       Layout const & layout() const;
+       /// Do not pass a temporary to this!
+       void setLayout(Layout const & layout);
+       ///
+       void setPlainOrDefaultLayout(DocumentClass const & tc);
        ///
-       void layout(LayoutPtr const & new_layout);
+       void setDefaultLayout(DocumentClass const & tc);
+       ///
+       void setPlainLayout(DocumentClass const & tc);
 
        /// This is the item depth, only used by enumerate and itemize
        signed char itemdepth;
 
-       ///
-       InsetBibitem * bibitem() const;  // ale970302
-
        /// look up change at given pos
        Change const & lookupChange(pos_type pos) const;
 
-       /// is there a change within the given range ?
+       /// is there a change within the given range (does not
+       /// check contained paragraphs)
        bool isChanged(pos_type start, pos_type end) const;
        /// is there an unchanged char at the given pos ?
-       bool isUnchanged(pos_type pos) const;
+       bool isChanged(pos_type pos) const;
+
        /// is there an insertion at the given pos ?
        bool isInserted(pos_type pos) const;
        /// is there a deletion at the given pos ?
        bool isDeleted(pos_type pos) const;
+       /// is the whole paragraph deleted ?
+       bool isDeleted(pos_type start, pos_type end) const;
 
        /// will the paragraph be physically merged with the next
        /// one if the imaginary end-of-par character is logically deleted?
@@ -197,10 +287,10 @@ public:
        void setChange(pos_type pos, Change const & change);
 
        /// accept changes within the given range
-       void acceptChanges(BufferParams const & bparams, pos_type start, pos_type end);
+       void acceptChanges(pos_type start, pos_type end);
 
        /// reject changes within the given range
-       void rejectChanges(BufferParams const & bparams, pos_type start, pos_type end);
+       void rejectChanges(pos_type start, pos_type end);
 
        /// Paragraphs can contain "manual labels", for example, Description
        /// environment. The text for this user-editable label is stored in
@@ -212,47 +302,47 @@ public:
        void setBeginOfBody();
 
        ///
-       docstring const & getLabelstring() const;
-
+       docstring expandLabel(Layout const &, BufferParams const &) const;
+       ///
+       docstring expandDocBookLabel(Layout const &, BufferParams const &) const;
+       ///
+       docstring const & labelString() const;
        /// the next two functions are for the manual labels
        docstring const getLabelWidthString() const;
        /// Set label width string.
        void setLabelWidthString(docstring const & s);
-       /// translate \p label to the paragraph language if possible.
-       docstring const translateIfPossible(docstring const & label,
-               BufferParams const & bparams) const;
-       /// Expand the counters for the labelstring of \c layout
-       docstring expandLabel(LayoutPtr const &, BufferParams const &,
-               bool process_appendix = true) const;
        /// Actual paragraph alignment used
-       char getAlign() const;
+       LyXAlignment getAlign() const;
        /// The nesting depth of a paragraph
        depth_type getDepth() const;
        /// The maximal possible depth of a paragraph after this one
        depth_type getMaxDepthAfter() const;
        ///
-       void applyLayout(LayoutPtr const & new_layout);
+       void applyLayout(Layout const & new_layout);
 
        /// (logically) erase the char at pos; return true if it was actually erased
        bool eraseChar(pos_type pos, bool trackChanges);
        /// (logically) erase the given range; return the number of chars actually erased
        int eraseChars(pos_type start, pos_type end, bool trackChanges);
 
+       ///
+       void resetFonts(Font const & font);
+
        /** Get uninstantiated font setting. Returns the difference
            between the characters font and the layoutfont.
            This is what is stored in the fonttable
        */
-       Font const
+       Font const &
        getFontSettings(BufferParams const &, pos_type pos) const;
        ///
-       Font const getFirstFontSettings(BufferParams const &) const;
+       Font const getFirstFontSettings(BufferParams const &) const;
 
        /** Get fully instantiated font. If pos == -1, use the layout
            font attached to this paragraph.
            If pos == -2, use the label font of the layout attached here.
            In all cases, the font is instantiated, i.e. does not have any
-           attributes with values Font::INHERIT, Font::IGNORE or
-           Font::TOGGLE.
+           attributes with values FONT_INHERIT, FONT_IGNORE or
+           FONT_TOGGLE.
        */
        Font const getFont(BufferParams const &, pos_type pos,
                              Font const & outerfont) const;
@@ -268,15 +358,12 @@ public:
         */
        FontSpan fontSpan(pos_type pos) const;
        ///
-       /// this is a bottleneck.
-       value_type getChar(pos_type pos) const { return text_[pos]; }
+       char_type getChar(pos_type pos) const;
        /// Get the char, but mirror all bracket characters if it is right-to-left
-       value_type getUChar(BufferParams const &, pos_type pos) const;
+       char_type getUChar(BufferParams const &, OutputParams const &,
+                          pos_type pos) const;
        /// pos <= size() (there is a dummy font change at the end of each par)
        void setFont(pos_type pos, Font const & font);
-       /// Returns the height of the highest font in range
-       Font_size highestFontInRange(pos_type startpos,
-                                       pos_type endpos, Font_size def_size) const;
        ///
        void insert(pos_type pos, docstring const & str,
                    Font const & font, Change const & change);
@@ -285,23 +372,20 @@ public:
        void appendString(docstring const & s, Font const & font,
                Change const & change);
        ///
-       void appendChar(value_type c, Font const & font, Change const & change);
+       void appendChar(char_type c, Font const & font, Change const & change);
        ///
-       void insertChar(pos_type pos, value_type c, bool trackChanges);
+       void insertChar(pos_type pos, char_type c, bool trackChanges);
        ///
-       void insertChar(pos_type pos, value_type c,
+       void insertChar(pos_type pos, char_type c,
                        Font const &, bool trackChanges);
        ///
-       void insertChar(pos_type pos, value_type c,
+       void insertChar(pos_type pos, char_type c,
                        Font const &, Change const & change);
-       ///
-       void insertInset(pos_type pos, Inset * inset,
-                        Change const & change);
-       ///
-       void insertInset(pos_type pos, Inset * inset,
-                        Font const &, Change const & change);
-       ///
-       bool insetAllowed(InsetCode code);
+       /// Insert \p inset at position \p pos with \p change traking status and
+       /// \p font.
+       /// \return true if successful.
+       bool insertInset(pos_type pos, Inset * inset,
+                        Font const & font, Change const & change);
        ///
        Inset * getInset(pos_type pos);
        ///
@@ -315,23 +399,37 @@ public:
 
        ///
        InsetList const & insetList() const;
+       ///
+       void setInsetBuffers(Buffer &);
+       ///
+       void resetBuffer();
 
        ///
        bool isHfill(pos_type pos) const;
 
        /// hinted by profiler
-       bool isInset(pos_type pos) const {
-               return getChar(pos) == static_cast<value_type>(META_INSET);
-       }
+       bool isInset(pos_type pos) const;
        ///
        bool isNewline(pos_type pos) const;
+       ///
+       bool isEnvSeparator(pos_type pos) const;
        /// return true if the char is a word separator
-       bool isSeparator(pos_type pos) const { return getChar(pos) == ' '; }
+       bool isSeparator(pos_type pos) const;
        ///
        bool isLineSeparator(pos_type pos) const;
-       /// True if the character/inset at this point can be part of a word.
-       /// Note that digits in particular are considered as letters
-       bool isLetter(pos_type pos) const;
+       /// True if the character/inset at this point is a word separator.
+       /// Note that digits in particular are not considered as word separator.
+       bool isWordSeparator(pos_type pos) const;
+       /// True if the element at this point is a character that is not a letter.
+       bool isChar(pos_type pos) const;
+       /// True if the element at this point is a space
+       bool isSpace(pos_type pos) const;
+       /// True if the element at this point is a hard hyphen or a apostrophe
+       /// If it is enclosed by spaces return false
+       bool isHardHyphenOrApostrophe(pos_type pos) const;
+       /// Return true if this paragraph has verbatim content that needs to be
+       /// protected by \cprotect
+       bool needsCProtection(bool const fragile = false) const;
 
        /// returns true if at least one line break or line separator has been deleted
        /// at the beginning of the paragraph (either physically or logically)
@@ -343,12 +441,12 @@ public:
        /// return true if we allow this par to stay empty
        bool allowEmpty() const;
        ///
-       char_type transformChar(char_type c, pos_type pos) const;
-       ///
        ParagraphParameters & params();
        ///
        ParagraphParameters const & params() const;
 
+       /// Check whether a call to fixBiblio is needed.
+       bool brokenBiblio() const;
        /// Check if we are in a Biblio environment and insert or
        /// delete InsetBibitems as necessary.
        /// \retval int 1, if we had to add an inset, in which case
@@ -356,23 +454,77 @@ public:
        /// an inset, in which case pos is the position from which the inset
        /// was deleted, and the cursor will need to be moved back one if it
        /// was previously past that position. Return 0 otherwise.
-       int checkBiblio(bool track_changes);
+       int fixBiblio(Buffer const & buffer);
 
        /// For each author, set 'used' to true if there is a change
        /// by this author in the paragraph.
        void checkAuthors(AuthorList const & authorList);
 
-       /// return the number of InsetOptArg in a paragraph
-       int numberOfOptArgs() const;
+       ///
+       void changeCase(BufferParams const & bparams, pos_type pos,
+               pos_type & right, TextCase action);
+
+       /// find \param str string inside Paragraph.
+       /// \return non-zero if the specified string is at the specified
+       ///     position; returned value is the actual match length in positions
+       /// \param del specifies whether deleted strings in ct mode will be considered
+       int find(
+               docstring const & str, ///< string to search
+               bool cs, ///<
+               bool mw, ///<
+               pos_type pos, ///< start from here.
+               bool del = true) const;
+
+       void locateWord(pos_type & from, pos_type & to,
+               word_location const loc) const;
+       ///
+       void updateWords();
+
+       /// Spellcheck word at position \p from and fill in found misspelled word
+       /// and \p suggestions if \p do_suggestion is true.
+       /// \return result from spell checker, SpellChecker::UNKNOWN_WORD when misspelled.
+       SpellChecker::Result spellCheck(pos_type & from, pos_type & to, WordLangTuple & wl,
+               docstring_list & suggestions, bool do_suggestion =  true,
+               bool check_learned = false) const;
+
+       /// Spell checker status at position \p pos.
+       /// If \p check_boundary is true the status of position immediately
+       /// before \p pos is tested too if it is at word boundary.
+       /// \return true if one of the tested positions is misspelled.
+       bool isMisspelled(pos_type pos, bool check_boundary = false) const;
+
+       /// \return the spell range (misspelled area) around position.
+       /// Range is empty if word at position is correctly spelled.
+       FontSpan const & getSpellRange(pos_type pos) const;
+
+       /// spell check of whole paragraph
+       /// remember results until call of requestSpellCheck()
+       void spellCheck() const;
+
+       /// query state of spell checker results
+       bool needsSpellCheck() const;
+       /// mark position of text manipulation to inform the spell checker
+       /// default value -1 marks the whole paragraph to be checked (again)
+       void requestSpellCheck(pos_type pos = -1);
+
+       /// an automatically generated identifying label for this paragraph.
+       /// presently used only in the XHTML output routines.
+       std::string magicLabel() const;
+
+       /// anonymizes the paragraph contents (but not the paragraphs
+       /// contained inside it. Does not handle undo.
+       void anonymize();
 
 private:
-       /**
-        * Keeping this here instead of in the pimpl makes LyX >10% faster
-        * for average tasks as buffer loading/switching etc.
-        */
-       typedef std::vector<value_type> TextContainer;
+       /// Expand the counters for the labelstring of \c layout
+       docstring expandParagraphLabel(Layout const &, BufferParams const &,
+               bool process_appendix) const;
+       ///
+       void deregisterWords();
+       ///
+       void collectWords();
        ///
-       TextContainer text_;
+       void registerWords();
 
        /// Pimpl away stuff
        class Private;