X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FText2.cpp;h=e0f5963f8b097f2acae567a675091391173b180b;hb=3a123b90af838b08680471d87170c38e56787df9;hp=fb6bd70f32fce5c92933b80cea63ff6c2419669b;hpb=96692bdbb0189b71803e83dbb18a2e3f006e7bf5;p=lyx.git diff --git a/src/Text2.cpp b/src/Text2.cpp index fb6bd70f32..e0f5963f8b 100644 --- a/src/Text2.cpp +++ b/src/Text2.cpp @@ -42,7 +42,7 @@ #include "TextClass.h" #include "TextMetrics.h" -#include "insets/InsetCollapsable.h" +#include "insets/InsetCollapsible.h" #include "mathed/InsetMathHull.h" @@ -295,7 +295,7 @@ void Text::setFont(Cursor & cur, Font const & font, bool toggleall) // Ok, we have a selection. Font newfont = font; - if (toggleall) { + if (toggleall) { // Toggling behaves as follows: We check the first character of the // selection. If it's (say) got EMPH on, then we set to off; if off, // then to on. With families and the like, we set it to INHERIT, if @@ -303,30 +303,30 @@ void Text::setFont(Cursor & cur, Font const & font, bool toggleall) CursorSlice const & sl = cur.selBegin(); Text const & text = *sl.text(); Paragraph const & par = text.getPar(sl.pit()); - + // get font at the position Font oldfont = par.getFont(cur.bv().buffer().params(), sl.pos(), text.outerFont(sl.pit())); FontInfo const & oldfi = oldfont.fontInfo(); - + FontInfo & newfi = newfont.fontInfo(); - + FontFamily newfam = newfi.family(); if (newfam != INHERIT_FAMILY && newfam != IGNORE_FAMILY && newfam == oldfi.family()) newfi.setFamily(INHERIT_FAMILY); - + FontSeries newser = newfi.series(); if (newser == BOLD_SERIES && oldfi.series() == BOLD_SERIES) newfi.setSeries(INHERIT_SERIES); - + FontShape newshp = newfi.shape(); if (newshp != INHERIT_SHAPE && newshp != IGNORE_SHAPE && newshp == oldfi.shape()) newfi.setShape(INHERIT_SHAPE); ColorCode newcol = newfi.color(); - if (newcol != Color_none && newcol != Color_inherit + if (newcol != Color_none && newcol != Color_inherit && newcol != Color_ignore && newcol == oldfi.color()) newfi.setColor(Color_none); @@ -337,6 +337,8 @@ void Text::setFont(Cursor & cur, Font const & font, bool toggleall) newfi.setUnderbar(oldfi.underbar() == FONT_OFF ? FONT_ON : FONT_OFF); if (newfi.strikeout() == FONT_TOGGLE) newfi.setStrikeout(oldfi.strikeout() == FONT_OFF ? FONT_ON : FONT_OFF); + if (newfi.xout() == FONT_TOGGLE) + newfi.setXout(oldfi.xout() == FONT_OFF ? FONT_ON : FONT_OFF); if (newfi.uuline() == FONT_TOGGLE) newfi.setUuline(oldfi.uuline() == FONT_OFF ? FONT_ON : FONT_OFF); if (newfi.uwave() == FONT_TOGGLE) @@ -347,7 +349,7 @@ void Text::setFont(Cursor & cur, Font const & font, bool toggleall) newfi.setNumber(oldfi.number() == FONT_OFF ? FONT_ON : FONT_OFF); } - setFont(cur.bv(), cur.selectionBegin().top(), + setFont(cur.bv(), cur.selectionBegin().top(), cur.selectionEnd().top(), newfont); } @@ -377,7 +379,7 @@ void Text::setFont(BufferView const & bv, CursorSlice const & begin, Font f = tm.displayFont(pit, pos); f.update(font, language); setCharFont(pit, pos, f, tm.font_); - // font change may change language... + // font change may change language... // spell checker has to know that pars_[pit].requestSpellCheck(pos); } @@ -449,7 +451,7 @@ docstring Text::getStringToIndex(Cursor const & cur) cur.message(_("Cannot index more than one paragraph!")); else return tmpcur.selectionAsString(false); - + return docstring(); } @@ -547,47 +549,23 @@ void Text::insertInset(Cursor & cur, Inset * inset) } -bool Text::setCursor(Cursor & cur, pit_type par, pos_type pos, +bool Text::setCursor(Cursor & cur, pit_type pit, pos_type pos, bool setfont, bool boundary) { TextMetrics const & tm = cur.bv().textMetrics(this); - bool const update_needed = !tm.contains(par); + bool const update_needed = !tm.contains(pit); Cursor old = cur; - setCursorIntern(cur, par, pos, setfont, boundary); + setCursorIntern(cur, pit, pos, setfont, boundary); return cur.bv().checkDepm(cur, old) || update_needed; } -void Text::setCursor(CursorSlice & cur, pit_type par, pos_type pos) -{ - LASSERT(par != int(paragraphs().size()), return); - cur.pit() = par; - cur.pos() = pos; - - // now some strict checking - Paragraph & para = getPar(par); - - // None of these should happen, but we're scaredy-cats - if (pos < 0) { - LYXERR0("Don't like -1!"); - LATTEST(false); - } - - if (pos > para.size()) { - LYXERR0("Don't like 1, pos: " << pos - << " size: " << para.size() - << " par: " << par); - LATTEST(false); - } -} - - -void Text::setCursorIntern(Cursor & cur, - pit_type par, pos_type pos, bool setfont, bool boundary) +void Text::setCursorIntern(Cursor & cur, pit_type pit, pos_type pos, + bool setfont, bool boundary) { LBUFERR(this == cur.text()); cur.boundary(boundary); - setCursor(cur.top(), par, pos); + cur.top().setPitPos(pit, pos); if (setfont) cur.setCurrentFont(); } @@ -614,6 +592,8 @@ bool Text::checkAndActivateInset(Cursor & cur, bool front) if (!front) --cur.pos(); inset->edit(cur, front); + cur.setCurrentFont(); + cur.boundary(false); return true; } @@ -630,8 +610,10 @@ bool Text::checkAndActivateInsetVisual(Cursor & cur, bool movingForward, bool mo return false; if (cur.selection() && cur.realAnchor().find(inset) == -1) return false; - inset->edit(cur, movingForward, + inset->edit(cur, movingForward, movingLeft ? Inset::ENTRY_DIRECTION_RIGHT : Inset::ENTRY_DIRECTION_LEFT); + cur.setCurrentFont(); + cur.boundary(false); return true; } @@ -663,11 +645,11 @@ bool Text::cursorBackward(Cursor & cur) !cur.paragraph().isSeparator(cur.pos() - 1)) { return setCursor(cur, cur.pit(), cur.pos(), true, true); } - + // go left and try to enter inset if (checkAndActivateInset(cur, false)) return false; - + // normal character left return setCursor(cur, cur.pit(), cur.pos() - 1, true, false); } @@ -693,7 +675,7 @@ bool Text::cursorVisLeft(Cursor & cur, bool skip_inset) cur = temp_cur; return false; } - return setCursor(cur, temp_cur.pit(), temp_cur.pos(), + return setCursor(cur, temp_cur.pit(), temp_cur.pos(), true, temp_cur.boundary()); } @@ -728,7 +710,7 @@ bool Text::cursorForward(Cursor & cur) if (cur.boundary() && !tm.isRTLBoundary(cur.pit(), cur.pos())) return setCursor(cur, cur.pit(), cur.pos(), true, false); - // next position is left of boundary, + // next position is left of boundary, // but go to next line for special cases like space, newline, linesep #if 0 // some effectless debug code to see the values in the debugger @@ -758,12 +740,12 @@ bool Text::cursorForward(Cursor & cur) return setCursor(cur, cur.pit(), cur.pos() + 1, true, true); } } - + // in front of RTL boundary? Stay on this side of the boundary because: // ab|cDDEEFFghi -> abc|DDEEFFghi if (tm.isRTLBoundary(cur.pit(), cur.pos() + 1)) return setCursor(cur, cur.pit(), cur.pos() + 1, true, true); - + // move right return setCursor(cur, cur.pit(), cur.pos() + 1, true, false); } @@ -803,9 +785,11 @@ bool Text::cursorDownParagraph(Cursor & cur) } -// fix the cursor `cur' after a characters has been deleted at `where' +namespace { +// fix the cursor `cur' after characters has been deleted at `where' // position. Called by deleteEmptyParagraphMechanism -void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where) +void fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where, + pos_type from, pos_type to) { // Do nothing if cursor is not in the paragraph where the // deletion occurred, @@ -813,8 +797,8 @@ void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where) return; // If cursor position is after the deletion place update it - if (cur.pos() > where.pos()) - --cur.pos(); + if (cur.pos() > from) + cur.pos() = max(from, cur.pos() - (to - from)); // Check also if we don't want to set the cursor on a spot behind the // pagragraph because we erased the last character. @@ -822,6 +806,8 @@ void Text::fixCursorAfterDelete(CursorSlice & cur, CursorSlice const & where) cur.pos() = cur.lastpos(); } +} + bool Text::deleteEmptyParagraphMechanism(Cursor & cur, Cursor & old, bool & need_anchor_change) @@ -857,29 +843,41 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur, if (&old.inset() == &cur[depth].inset()) break; - // Whether a common inset is found and whether the cursor is still in + // Whether a common inset is found and whether the cursor is still in // the same paragraph (possibly nested). bool const same_par = depth < cur.depth() && old.pit() == cur[depth].pit(); - bool const same_par_pos = depth == cur.depth() - 1 && same_par + bool const same_par_pos = depth == cur.depth() - 1 && same_par && old.pos() == cur[depth].pos(); - - // If the chars around the old cursor were spaces, delete one of them. + + // If the chars around the old cursor were spaces, delete some of + // them , but only if the cursor has really moved. if (!same_par_pos) { - // Only if the cursor has really moved. - if (old.pos() > 0 - && old.pos() < oldpar.size() - && oldpar.isLineSeparator(old.pos()) - && oldpar.isLineSeparator(old.pos() - 1) - && !oldpar.isDeleted(old.pos() - 1) - && !oldpar.isDeleted(old.pos())) { - oldpar.eraseChar(old.pos() - 1, cur.buffer()->params().track_changes); + // find range of spaces around cursors + int from = old.pos(); + while (from > 0 + && oldpar.isLineSeparator(from - 1) + && !oldpar.isDeleted(from - 1)) + --from; + int to = old.pos(); + while (to < oldpar.size() - 1 + && oldpar.isLineSeparator(to) + && !oldpar.isDeleted(to)) + ++to; + + // If we are not at the extremity of the paragraph, keep one space + if (from != to && from > 0 && to < oldpar.size()) + ++from; + + // Remove spaces and adapt cursor. + if (from < to) { + oldpar.eraseChars(from, to, cur.buffer()->params().track_changes); // FIXME: This will not work anymore when we have multiple views of the same buffer // In this case, we will have to correct also the cursors held by // other bufferviews. It will probably be easier to do that in a more // automated way in CursorSlice code. (JMarc 26/09/2001) // correct all cursor parts if (same_par) { - fixCursorAfterDelete(cur[depth], old.top()); + fixCursorAfterDelete(cur[depth], old.top(), from, to); need_anchor_change = true; } return true; @@ -904,12 +902,12 @@ bool Text::deleteEmptyParagraphMechanism(Cursor & cur, min(old.pit() + 1, old.lastpit())); ParagraphList & plist = old.text()->paragraphs(); bool const soa = oldpar.params().startOfAppendix(); - plist.erase(next(plist.begin(), old.pit())); + plist.erase(lyx::next(plist.begin(), old.pit())); // do not lose start of appendix marker (bug 4212) if (soa && old.pit() < pit_type(plist.size())) plist[old.pit()].params().startOfAppendix(true); - // see #warning (FIXME?) above + // see #warning (FIXME?) above if (cur.depth() >= old.depth()) { CursorSlice & curslice = cur[old.depth() - 1]; if (&curslice.inset() == &old.inset() @@ -948,13 +946,26 @@ void Text::deleteEmptyParagraphMechanism(pit_type first, pit_type last, bool tra if (par.isFreeSpacing()) continue; - for (pos_type pos = 1; pos < par.size(); ++pos) { - if (par.isLineSeparator(pos) && par.isLineSeparator(pos - 1) - && !par.isDeleted(pos - 1)) { - if (par.eraseChar(pos - 1, trackChanges)) { - --pos; - } - } + pos_type from = 0; + while (from < par.size()) { + // skip non-spaces + while (from < par.size() + && (!par.isLineSeparator(from) || par.isDeleted(from))) + ++from; + // find string of spaces + pos_type to = from; + while (to < par.size() + && par.isLineSeparator(to) && !par.isDeleted(to)) + ++to; + // empty? We are done + if (from == to) + break; + // if inside the line, keep one space + if (from > 0 && to < par.size()) + ++from; + // remove the extra spaces + if (from < to) + par.eraseChars(from, to, trackChanges); } // don't delete anything if this is the only remaining paragraph @@ -968,7 +979,7 @@ void Text::deleteEmptyParagraphMechanism(pit_type first, pit_type last, bool tra continue; if (par.empty() || (par.size() == 1 && par.isLineSeparator(0))) { - pars_.erase(next(pars_.begin(), pit)); + pars_.erase(lyx::next(pars_.begin(), pit)); --pit; --last; continue;