]> git.lyx.org Git - lyx.git/blobdiff - src/Text.cpp
Rename a variable
[lyx.git] / src / Text.cpp
index c1af0948a96a684776843a2857eefefee0caf554..2d916c834b3c08265e0d3938866e2d0201eeda33 100644 (file)
@@ -464,6 +464,9 @@ void Text::readParToken(Paragraph & par, Lexer & lex,
        } else if (token == "\\strikeout") {
                lex.next();
                font.fontInfo().setStrikeout(setLyXMisc(lex.getString()));
+       } else if (token == "\\xout") {
+               lex.next();
+               font.fontInfo().setXout(setLyXMisc(lex.getString()));
        } else if (token == "\\uuline") {
                lex.next();
                font.fontInfo().setUuline(setLyXMisc(lex.getString()));
@@ -905,12 +908,55 @@ void Text::insertStringAsParagraphs(Cursor & cur, docstring const & str,
 }
 
 
+namespace {
+
+bool canInsertChar(Cursor const & cur, char_type c)
+{
+       Paragraph const & par = cur.paragraph();
+       // If not in free spacing mode, check if there will be two blanks together or a blank at
+       // the beginning of a paragraph.
+       if (!par.isFreeSpacing() && isLineSeparatorChar(c)) {
+               if (cur.pos() == 0) {
+                       cur.message(_(
+                                       "You cannot insert a space at the "
+                                       "beginning of a paragraph. Please read the Tutorial."));
+                       return false;
+               }
+               // LASSERT: Is it safe to continue here?
+               LASSERT(cur.pos() > 0, /**/);
+               if ((par.isLineSeparator(cur.pos() - 1) || par.isNewline(cur.pos() - 1))
+                               && !par.isDeleted(cur.pos() - 1)) {
+                       cur.message(_(
+                                       "You cannot type two spaces this way. "
+                                       "Please read the Tutorial."));
+                       return false;
+               }
+       }
+
+       // Prevent to insert uncodable characters in verbatim and ERT.
+       // The encoding is inherited from the context here.
+       if (par.isPassThru() && cur.getEncoding()) {
+               Encoding const * e = cur.getEncoding();
+               if (!e->encodable(c)) {
+                       cur.message(_("Character is uncodable in this verbatim context."));
+                       return false;
+               }
+       }
+       return true;
+}
+
+} // namespace
+
+
 // insert a character, moves all the following breaks in the
 // same Paragraph one to the right and make a rebreak
 void Text::insertChar(Cursor & cur, char_type c)
 {
        LBUFERR(this == cur.text());
 
+       if (!canInsertChar(cur,c))
+               return;
+
        cur.recordUndo(INSERT_UNDO);
 
        TextMetrics const & tm = cur.bv().textMetrics(this);
@@ -919,20 +965,22 @@ void Text::insertChar(Cursor & cur, char_type c)
        // try to remove this
        pit_type const pit = cur.pit();
 
-       bool const freeSpacing = par.layout().free_spacing ||
-               par.isFreeSpacing();
-
        if (lyxrc.auto_number) {
                static docstring const number_operators = from_ascii("+-/*");
                static docstring const number_unary_operators = from_ascii("+-");
-               static docstring const number_separators = from_ascii(".,:");
 
+               // European Number Separators: comma, dot etc.
+               // European Number Terminators: percent, permille, degree, euro etc.
                if (cur.current_font.fontInfo().number() == FONT_ON) {
                        if (!isDigitASCII(c) && !contains(number_operators, c) &&
-                           !(contains(number_separators, c) &&
+                           !(isEuropeanNumberSeparator(c) &&
                              cur.pos() != 0 &&
                              cur.pos() != cur.lastpos() &&
                              tm.displayFont(pit, cur.pos()).fontInfo().number() == FONT_ON &&
+                             tm.displayFont(pit, cur.pos() - 1).fontInfo().number() == FONT_ON) &&
+                           !(isEuropeanNumberTerminator(c) &&
+                             cur.pos() != 0 &&
+                             tm.displayFont(pit, cur.pos()).fontInfo().number() == FONT_ON &&
                              tm.displayFont(pit, cur.pos() - 1).fontInfo().number() == FONT_ON)
                           )
                                number(cur); // Set current_font.number to OFF
@@ -950,7 +998,7 @@ void Text::insertChar(Cursor & cur, char_type c)
                                  ) {
                                        setCharFont(pit, cur.pos() - 1, cur.current_font,
                                                tm.font_);
-                               } else if (contains(number_separators, c)
+                               } else if (isEuropeanNumberSeparator(c)
                                     && cur.pos() >= 2
                                     && tm.displayFont(pit, cur.pos() - 2).fontInfo().number() == FONT_ON) {
                                        setCharFont(pit, cur.pos() - 1, cur.current_font,
@@ -1004,45 +1052,6 @@ void Text::insertChar(Cursor & cur, char_type c)
                }
        }
 
-       // Next check, if there will be two blanks together or a blank at
-       // the beginning of a paragraph.
-       // I decided to handle blanks like normal characters, the main
-       // difference are the special checks when calculating the row.fill
-       // (blank does not count at the end of a row) and the check here
-
-       // When the free-spacing option is set for the current layout,
-       // disable the double-space checking
-       if (!freeSpacing && isLineSeparatorChar(c)) {
-               if (cur.pos() == 0) {
-                       cur.message(_(
-                                       "You cannot insert a space at the "
-                                       "beginning of a paragraph. Please read the Tutorial."));
-                       return;
-               }
-               // LASSERT: Is it safe to continue here?
-               LASSERT(cur.pos() > 0, /**/);
-               if ((par.isLineSeparator(cur.pos() - 1) || par.isNewline(cur.pos() - 1))
-                               && !par.isDeleted(cur.pos() - 1)) {
-                       cur.message(_(
-                                       "You cannot type two spaces this way. "
-                                       "Please read the Tutorial."));
-                       return;
-               }
-       }
-
-       // Prevent to insert uncodable characters in verbatim and ERT
-       // (workaround for bug 9012)
-       // Don't do it for listings inset, since InsetListings::latex() tries
-       // to switch to a usable encoding which works in many cases (bug 9102).
-       if (cur.paragraph().isPassThru() && owner_->lyxCode() != LISTINGS_CODE &&
-           cur.current_font.language()) {
-               Encoding const * e = cur.current_font.language()->encoding();
-               if (!e->encodable(c)) {
-                       cur.message(_("Character is uncodable in verbatim paragraphs."));
-                       return;
-               }
-       }
-
        pos_type pos = cur.pos();
        if (!cur.paragraph().isPassThru() && owner_->lyxCode() != IPA_CODE &&
            cur.real_current_font.fontInfo().family() != TYPEWRITER_FAMILY &&
@@ -1057,11 +1066,6 @@ void Text::insertChar(Cursor & cur, char_type c)
                        par.eraseChar(pos - 1, cur.buffer()->params().track_changes);
                        c = 0x2014;
                        pos--;
-               } else if (par.getChar(pos - 1) == 0x2014) {
-                       // convert "----" to "-"
-                       par.eraseChar(pos - 1, cur.buffer()->params().track_changes);
-                       c = '-';
-                       pos--;
                }
        }
 
@@ -1477,7 +1481,7 @@ void Text::deleteWordForward(Cursor & cur, bool const force)
                cursorForwardOneWord(cur);
                cur.setSelection();
                if (force || !cur.confirmDeletion()) {
-                       cutSelection(cur, true, false);
+                       cutSelection(cur, false);
                        cur.checkBufferStructure();
                }
        }
@@ -1495,7 +1499,7 @@ void Text::deleteWordBackward(Cursor & cur, bool const force)
                cursorBackwardOneWord(cur);
                cur.setSelection();
                if (force || !cur.confirmDeletion()) {
-                       cutSelection(cur, true, false);
+                       cutSelection(cur, false);
                        cur.checkBufferStructure();
                }
        }
@@ -1747,20 +1751,24 @@ bool Text::dissolveInset(Cursor & cur)
        cur.recordUndoInset();
        cur.setMark(false);
        cur.selHandle(false);
-       // save position
+       // save position inside inset
        pos_type spos = cur.pos();
        pit_type spit = cur.pit();
        ParagraphList plist;
        if (cur.lastpit() != 0 || cur.lastpos() != 0)
                plist = paragraphs();
        cur.popBackward();
-       // store cursor offset
+       // update cursor offset
        if (spit == 0)
                spos += cur.pos();
        spit += cur.pit();
-       Buffer & b = *cur.buffer();
-       cur.paragraph().eraseChar(cur.pos(), b.params().track_changes);
+       // remember position outside inset to delete inset later
+       // we do not do it now to avoid memory reuse issues (see #10667).
+       DocIterator inset_it = cur;
+       // jump over inset
+       ++cur.pos();
 
+       Buffer & b = *cur.buffer();
        if (!plist.empty()) {
                // see bug 7319
                // we clear the cache so that we won't get conflicts with labels
@@ -1781,17 +1789,20 @@ bool Text::dissolveInset(Cursor & cur)
 
                pasteParagraphList(cur, plist, b.params().documentClassPtr(),
                                   b.errorList("Paste"));
-               // restore position
-               cur.pit() = min(cur.lastpit(), spit);
-               cur.pos() = min(cur.lastpos(), spos);
        }
 
-       cur.forceBufferUpdate();
+       // delete the inset now
+       inset_it.paragraph().eraseChar(inset_it.pos(), b.params().track_changes);
 
+       // restore position
+       cur.pit() = min(cur.lastpit(), spit);
+       cur.pos() = min(cur.lastpos(), spos);
        // Ensure the current language is set correctly (bug 6292)
        cur.text()->setCursor(cur, cur.pit(), cur.pos());
        cur.clearSelection();
        cur.resetAnchor();
+       cur.forceBufferUpdate();
+
        return true;
 }
 
@@ -1887,7 +1898,7 @@ bool Text::read(Lexer & lex,
 
 
 // Returns the current font and depth as a message.
-docstring Text::currentState(Cursor const & cur) const
+docstring Text::currentState(Cursor const & cur, bool devel_mode) const
 {
        LBUFERR(this == cur.text());
        Buffer & buf = *cur.buffer();
@@ -1944,34 +1955,66 @@ docstring Text::currentState(Cursor const & cur) const
                }
        }
 
-#ifdef DEVEL_VERSION
-       os << _(", Inset: ") << &cur.inset();
-       os << _(", Paragraph: ") << cur.pit();
-       os << _(", Id: ") << par.id();
-       os << _(", Position: ") << cur.pos();
-       // FIXME: Why is the check for par.size() needed?
-       // We are called with cur.pos() == par.size() quite often.
-       if (!par.empty() && cur.pos() < par.size()) {
-               // Force output of code point, not character
-               size_t const c = par.getChar(cur.pos());
-               os << _(", Char: 0x") << hex << c;
+       if (devel_mode) {
+               os << _(", Inset: ") << &cur.inset();
+               os << _(", Paragraph: ") << cur.pit();
+               os << _(", Id: ") << par.id();
+               os << _(", Position: ") << cur.pos();
+               // FIXME: Why is the check for par.size() needed?
+               // We are called with cur.pos() == par.size() quite often.
+               if (!par.empty() && cur.pos() < par.size()) {
+                       // Force output of code point, not character
+                       size_t const c = par.getChar(cur.pos());
+                       os << _(", Char: 0x") << hex << c;
+               }
+               os << _(", Boundary: ") << cur.boundary();
+//             Row & row = cur.textRow();
+//             os << bformat(_(", Row b:%1$d e:%2$d"), row.pos(), row.endpos());
        }
-       os << _(", Boundary: ") << cur.boundary();
-//     Row & row = cur.textRow();
-//     os << bformat(_(", Row b:%1$d e:%2$d"), row.pos(), row.endpos());
-#endif
        return os.str();
 }
 
 
 docstring Text::getPossibleLabel(Cursor const & cur) const
 {
-       pit_type pit = cur.pit();
+       pit_type textpit = cur.pit();
+       Layout const * layout = &(pars_[textpit].layout());
 
-       Layout const * layout = &(pars_[pit].layout());
+       // Will contain the label prefix.
+       docstring name;
+
+       // For captions, we just take the caption type
+       Inset * caption_inset = cur.innerInsetOfType(CAPTION_CODE);
+       if (caption_inset) {
+               string const & ftype = static_cast<InsetCaption *>(caption_inset)->floattype();
+               FloatList const & fl = cur.buffer()->params().documentClass().floats();
+               if (fl.typeExist(ftype)) {
+                       Floating const & flt = fl.getType(ftype);
+                       name = from_utf8(flt.refPrefix());
+               }
+               if (name.empty())
+                       name = from_utf8(ftype.substr(0,3));
+       } else {
+               // For section, subsection, etc...
+               if (layout->latextype == LATEX_PARAGRAPH && textpit != 0) {
+                       Layout const * layout2 = &(pars_[textpit - 1].layout());
+                       if (layout2->latextype != LATEX_PARAGRAPH) {
+                               --textpit;
+                               layout = layout2;
+                       }
+               }
+               if (layout->latextype != LATEX_PARAGRAPH)
+                       name = layout->refprefix;
+
+               // If none of the above worked, see if the inset knows.
+               if (name.empty()) {
+                       InsetLayout const & il = cur.inset().getLayout();
+                       name = il.refprefix();
+               }
+       }
 
        docstring text;
-       docstring par_text = pars_[pit].asString();
+       docstring par_text = pars_[textpit].asString(AS_STR_SKIPDELETE);
 
        // The return string of math matrices might contain linebreaks
        par_text = subst(par_text, '\n', '-');
@@ -1992,46 +2035,13 @@ docstring Text::getPossibleLabel(Cursor const & cur) const
        if (text.size() > max_label_length)
                text.resize(max_label_length);
 
-       // Will contain the label prefix.
-       docstring name;
-
-       // For section, subsection, etc...
-       if (layout->latextype == LATEX_PARAGRAPH && pit != 0) {
-               Layout const * layout2 = &(pars_[pit - 1].layout());
-               if (layout2->latextype != LATEX_PARAGRAPH) {
-                       --pit;
-                       layout = layout2;
-               }
-       }
-       if (layout->latextype != LATEX_PARAGRAPH)
-               name = layout->refprefix;
-
-       // For captions, we just take the caption type
-       Inset * caption_inset = cur.innerInsetOfType(CAPTION_CODE);
-       if (caption_inset) {
-               string const & ftype = static_cast<InsetCaption *>(caption_inset)->floattype();
-               FloatList const & fl = cur.buffer()->params().documentClass().floats();
-               if (fl.typeExist(ftype)) {
-                       Floating const & flt = fl.getType(ftype);
-                       name = from_utf8(flt.refPrefix());
-               }
-               if (name.empty())
-                       name = from_utf8(ftype.substr(0,3));
-       }
-
-       // If none of the above worked, see if the inset knows.
-       if (name.empty()) {
-               InsetLayout const & il = cur.inset().getLayout();
-               name = il.refprefix();
-       }
-
        if (!name.empty())
                text = name + ':' + text;
 
        // We need a unique label
        docstring label = text;
        int i = 1;
-       while (cur.buffer()->insetLabel(label)) {
+       while (cur.buffer()->activeLabel(label)) {
                        label = text + '-' + convert<docstring>(i);
                        ++i;
                }
@@ -2183,7 +2193,8 @@ docstring Text::previousWord(CursorSlice const & sl) const
 bool Text::completionSupported(Cursor const & cur) const
 {
        Paragraph const & par = cur.paragraph();
-       return cur.pos() > 0
+       return !cur.selection()
+               && cur.pos() > 0
                && (cur.pos() >= par.size() || par.isWordSeparator(cur.pos()))
                && !par.isWordSeparator(cur.pos() - 1);
 }