X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FText3.cpp;h=ce6811452700f437ba63459a2d9806c3a78c539e;hb=23832ce191e0d63088dbb6a02e9f0ebc73472004;hp=69015cac62a76326e39b8e04ad79266ead93f612;hpb=108a67ed433821fba346ddc0adb28483a0154e2a;p=lyx.git diff --git a/src/Text3.cpp b/src/Text3.cpp index 69015cac62..ce68114527 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -45,7 +45,6 @@ #include "SpellChecker.h" #include "TextClass.h" #include "TextMetrics.h" -#include "VSpace.h" #include "WordLangTuple.h" #include "frontends/Application.h" @@ -68,6 +67,7 @@ #include "support/convert.h" #include "support/debug.h" #include "support/gettext.h" +#include "support/lassert.h" #include "support/lstrings.h" #include "support/lyxtime.h" #include "support/os.h" @@ -93,6 +93,7 @@ using cap::pasteClipboardGraphics; using cap::replaceSelection; using cap::grabAndEraseSelection; using cap::selClearOrDel; +using cap::pasteSimpleText; // globals... static Font freefont(ignore_font, ignore_language); @@ -245,8 +246,11 @@ static bool doInsertInset(Cursor & cur, Text * text, if (edit) inset->edit(cur, true); // Now put this into inset - cur.text()->insertStringAsLines(cur, ds, cur.current_font); - cur.leaveInset(*inset); + Font const f(inherit_font, cur.current_font.language()); + if (!ds.empty()) { + cur.text()->insertStringAsLines(cur, ds, f); + cur.leaveInset(*inset); + } return true; } @@ -268,10 +272,10 @@ static bool doInsertInset(Cursor & cur, Text * text, cur.buffer()->errors("Paste"); cur.clearSelection(); // bug 393 cur.finishUndo(); - InsetText * insetText = dynamic_cast(inset); - if (insetText) { - insetText->fixParagraphsFont(); - if (!insetText->allowMultiPar() || cur.lastpit() == 0) { + InsetText * inset_text = inset->asInsetText(); + if (inset_text) { + inset_text->fixParagraphsFont(); + if (!inset_text->allowMultiPar() || cur.lastpit() == 0) { // reset first par to default cur.text()->paragraphs().begin() ->setPlainOrDefaultLayout(bparams.documentClass()); @@ -464,12 +468,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // FIXME: We use the update flag to indicates wether a singlePar or a // full screen update is needed. We reset it here but shall we restore it // at the end? - cur.noUpdate(); + cur.noScreenUpdate(); LASSERT(cur.text() == this, /**/); - CursorSlice oldTopSlice = cur.top(); - bool oldBoundary = cur.boundary(); - bool sel = cur.selection(); + CursorSlice const oldTopSlice = cur.top(); + bool const oldBoundary = cur.boundary(); + bool const oldSelection = cur.selection(); // Signals that, even if needsUpdate == false, an update of the // cursor paragraph is required bool singleParUpdate = lyxaction.funcHasFlag(cmd.action(), @@ -477,7 +481,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // Signals that a full-screen update is required bool needsUpdate = !(lyxaction.funcHasFlag(cmd.action(), LyXAction::NoUpdate) || singleParUpdate); - + bool const last_misspelled = lyxrc.spellcheck_continuously + && cur.paragraph().isMisspelled(cur.pos(), true); + FuncCode const act = cmd.action(); switch (act) { @@ -486,8 +492,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) recUndo(cur, pit, pit + 1); cur.finishUndo(); pars_.swap(pit, pit + 1); - cur.buffer()->updateBuffer(); needsUpdate = true; + cur.forceBufferUpdate(); ++cur.pit(); break; } @@ -497,9 +503,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) recUndo(cur, pit - 1, pit); cur.finishUndo(); pars_.swap(pit, pit - 1); - cur.buffer()->updateBuffer(); --cur.pit(); needsUpdate = true; + cur.forceBufferUpdate(); break; } @@ -523,7 +529,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) par.params().startOfAppendix(start); // we can set the refreshing parameters now - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); break; } @@ -558,7 +564,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cursorTop(cur); else cur.undispatched(); - cur.updateFlags(Update::FitCursor); + cur.screenUpdateFlags(Update::FitCursor); break; case LFUN_BUFFER_END: @@ -568,7 +574,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cursorBottom(cur); else cur.undispatched(); - cur.updateFlags(Update::FitCursor); + cur.screenUpdateFlags(Update::FitCursor); break; case LFUN_INSET_BEGIN: @@ -578,7 +584,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cursorTop(cur); else cur.undispatched(); - cur.updateFlags(Update::FitCursor); + cur.screenUpdateFlags(Update::FitCursor); break; case LFUN_INSET_END: @@ -588,7 +594,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cursorBottom(cur); else cur.undispatched(); - cur.updateFlags(Update::FitCursor); + cur.screenUpdateFlags(Update::FitCursor); break; case LFUN_INSET_SELECT_ALL: @@ -600,7 +606,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cursorBottom(cur); } else cur.undispatched(); - cur.updateFlags(Update::FitCursor); + cur.screenUpdateFlags(Update::FitCursor); break; case LFUN_CHAR_FORWARD: @@ -624,7 +630,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // provide it with two different cursors. Cursor dummy = cur; dummy.pos() = dummy.pit() = 0; - cur.bv().checkDepm(dummy, cur); + if (cur.bv().checkDepm(dummy, cur)) { + cur.forceBufferUpdate(); + // DEPM may have requested a screen update + cur.screenUpdateFlags( + cur.screenUpdate() | dummy.screenUpdate()); + } } } break; @@ -650,7 +661,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) Cursor dummy = cur; dummy.pos() = cur.lastpos(); dummy.pit() = cur.lastpit(); - cur.bv().checkDepm(dummy, cur); + if (cur.bv().checkDepm(dummy, cur)) { + cur.forceBufferUpdate(); + // DEPM may have requested a screen update + cur.screenUpdateFlags( + cur.screenUpdate() | dummy.screenUpdate()); + } } } break; @@ -817,6 +833,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_FORWARD_SELECT: needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_FORWARD_SELECT); needsUpdate |= cursorForwardOneWord(cur); + + if (!needsUpdate && oldTopSlice == cur.top() + && cur.boundary() == oldBoundary) { + cur.undispatched(); + cmd = FuncRequest(LFUN_FINISHED_FORWARD); + + // we will probably be moving out the inset, so we should execute + // the depm-mechanism, but only when the cursor has a place to + // go outside this inset, i.e. in a slice above. + if (cur.depth() > 1 && cur.pos() == cur.lastpos() + && cur.pit() == cur.lastpit()) { + // The cursor hasn't changed yet. To give the + // DEPM the possibility of doing something we must + // provide it with two different cursors. + Cursor dummy = cur; + dummy.pos() = dummy.pit() = 0; + if (cur.bv().checkDepm(dummy, cur)) { + cur.forceBufferUpdate(); + // DEPM may have requested a screen update + cur.screenUpdateFlags( + cur.screenUpdate() | dummy.screenUpdate()); + } + } + } break; case LFUN_WORD_LEFT: @@ -846,6 +886,31 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_BACKWARD_SELECT: needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_BACKWARD_SELECT); needsUpdate |= cursorBackwardOneWord(cur); + + if (!needsUpdate && oldTopSlice == cur.top() + && cur.boundary() == oldBoundary) { + cur.undispatched(); + cmd = FuncRequest(LFUN_FINISHED_BACKWARD); + + // we will probably be moving out the inset, so we should execute + // the depm-mechanism, but only when the cursor has a place to + // go outside this inset, i.e. in a slice above. + if (cur.depth() > 1 && cur.pos() == 0 + && cur.pit() == 0) { + // The cursor hasn't changed yet. To give the + // DEPM the possibility of doing something we must + // provide it with two different cursors. + Cursor dummy = cur; + dummy.pos() = cur.lastpos(); + dummy.pit() = cur.lastpit(); + if (cur.bv().checkDepm(dummy, cur)) { + cur.forceBufferUpdate(); + // DEPM may have requested a screen update + cur.screenUpdateFlags( + cur.screenUpdate() | dummy.screenUpdate()); + } + } + } break; case LFUN_WORD_SELECT: { @@ -909,24 +974,22 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) pit_type const pit_end = cur.selEnd().pit(); for (pit_type pit = cur.selBegin().pit(); pit <= pit_end; pit++) { Paragraph & par = paragraphs()[pit]; - if (par.getChar(0) == '\t') { - if (cur.pit() == pit) - cur.posBackward(); - if (cur.realAnchor().pit() == pit && cur.realAnchor().pos() > 0 ) - cur.realAnchor().backwardPos(); - - par.eraseChar(0, tc); - } else - // If no tab was present, try to remove up to four spaces. - for (int n_spaces = 0; - par.getChar(0) == ' ' && n_spaces < 4; ++n_spaces) { + if (par.empty()) + continue; + char_type const c = par.getChar(0); + if (c == '\t' || c == ' ') { + // remove either 1 tab or 4 spaces. + int const n = (c == ' ' ? 4 : 1); + for (int i = 0; i < n + && !par.empty() && par.getChar(0) == c; ++i) { if (cur.pit() == pit) cur.posBackward(); - if (cur.realAnchor().pit() == pit && cur.realAnchor().pos() > 0 ) + if (cur.realAnchor().pit() == pit + && cur.realAnchor().pos() > 0 ) cur.realAnchor().backwardPos(); - par.eraseChar(0, tc); } + } } cur.finishUndo(); } else { @@ -1032,7 +1095,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (cur.selection()) cutSelection(cur, true, false); cur.insert(inset); - cur.posForward(); + if (inset->editable() && inset->asInsetText()) + inset->edit(cur, true); + else + cur.posForward(); // trigger InstantPreview now if (inset->lyxCode() == EXTERNAL_CODE) { @@ -1046,8 +1112,10 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_INSET_DISSOLVE: { - if (dissolveInset(cur)) + if (dissolveInset(cur)) { needsUpdate = true; + cur.forceBufferUpdate(); + } break; } @@ -1269,6 +1337,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bv->buffer().errors("Paste"); break; + case LFUN_CLIPBOARD_PASTE_SIMPLE: + cur.clearSelection(); + pasteSimpleText(cur, cmd.argument() == "paragraph"); + break; + case LFUN_PRIMARY_SELECTION_PASTE: pasteString(cur, theSelection().get(), cmd.argument() == "paragraph"); @@ -1299,33 +1372,34 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_QUOTE_INSERT: { - Paragraph & par = cur.paragraph(); + // this avoids a double undo + // FIXME: should not be needed, ideally + if (!cur.selection()) + cur.recordUndo(); + cap::replaceSelection(cur); + + Paragraph const & par = cur.paragraph(); pos_type pos = cur.pos(); + BufferParams const & bufparams = bv->buffer().params(); - Layout const & style = par.layout(); - InsetLayout const & ilayout = cur.inset().getLayout(); - if (!style.pass_thru && !ilayout.isPassThru() - && par.getFontSettings(bufparams, pos).language()->lang() != "hebrew") { - // this avoids a double undo - // FIXME: should not be needed, ideally - if (!cur.selection()) - cur.recordUndo(); - cap::replaceSelection(cur); - pos = cur.pos(); - char_type c; - if (pos == 0) - c = ' '; - else if (cur.prevInset() && cur.prevInset()->isSpace()) - c = ' '; - else + bool const hebrew = + par.getFontSettings(bufparams, pos).language()->lang() == "hebrew"; + bool const allow_inset_quote = !(par.isPassThru() || hebrew); + + if (allow_inset_quote) { + char_type c = ' '; + if (pos > 0 && (!cur.prevInset() || !cur.prevInset()->isSpace())) c = par.getChar(pos - 1); - string arg = to_utf8(cmd.argument()); - cur.insert(new InsetQuotes(cur.buffer(), c, (arg == "single") - ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes)); + string const arg = to_utf8(cmd.argument()); + InsetQuotes::QuoteTimes const quote_type = (arg == "single") + ? InsetQuotes::SingleQuotes : InsetQuotes::DoubleQuotes; + cur.insert(new InsetQuotes(cur.buffer(), c, quote_type)); cur.posForward(); - } - else + } else { + // The cursor might have been invalidated by the replaceSelection. + cur.buffer()->changed(true); lyx::dispatch(FuncRequest(LFUN_SELF_INSERT, "\"")); + } break; } @@ -1363,7 +1437,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case mouse_button::button1: // Set the cursor if (!bv->mouseSetCursor(cur, cmd.argument() == "region-select")) - cur.updateFlags(Update::SinglePar | Update::FitCursor); + cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); if (bvcur.wordSelection()) selectWord(bvcur, WHOLE_WORD); break; @@ -1374,7 +1448,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) lyx::dispatch( FuncRequest(LFUN_COMMAND_ALTERNATIVES, "selection-paste ; primary-selection-paste paragraph")); - cur.noUpdate(); + cur.noScreenUpdate(); break; case mouse_button::button3: { @@ -1382,11 +1456,11 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // selection, a context menu will popup. if (bvcur.selection() && cur >= bvcur.selectionBegin() && cur < bvcur.selectionEnd()) { - cur.noUpdate(); + cur.noScreenUpdate(); return; } if (!bv->mouseSetCursor(cur, false)) - cur.updateFlags(Update::SinglePar | Update::FitCursor); + cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); break; } @@ -1398,7 +1472,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_MOUSE_MOTION: { // Mouse motion with right or middle mouse do nothing for now. if (cmd.button() != mouse_button::button1) { - cur.noUpdate(); + cur.noScreenUpdate(); return; } // ignore motions deeper nested than the real anchor @@ -1431,8 +1505,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bvcur.setSelection(true); if (cur.top() == old) { // We didn't move one iota, so no need to update the screen. - cur.updateFlags(Update::SinglePar | Update::FitCursor); - //cur.noUpdate(); + cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); + //cur.noScreenUpdate(); return; } break; @@ -1453,23 +1527,23 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) cur.bv().cursor().setSelection(); // We might have removed an empty but drawn selection // (probably a margin) - cur.updateFlags(Update::SinglePar | Update::FitCursor); + cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); } else - cur.noUpdate(); + cur.noScreenUpdate(); // FIXME: We could try to handle drag and drop of selection here. return; case mouse_button::button2: // Middle mouse pasting is handled at mouse press time, // see LFUN_MOUSE_PRESS. - cur.noUpdate(); + cur.noScreenUpdate(); return; case mouse_button::button3: // Cursor was set at LFUN_MOUSE_PRESS time. // FIXME: If there is a selection we could try to handle a special // drag & drop context menu. - cur.noUpdate(); + cur.noScreenUpdate(); return; case mouse_button::none: @@ -1502,6 +1576,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) cur.resetAnchor(); moveCursor(cur, false); + cur.markNewWordPosition(); bv->bookmarkEditPosition(); break; } @@ -1515,7 +1590,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } p["target"] = (cmd.argument().empty()) ? content : cmd.argument(); - string const data = InsetCommand::params2string("href", p); + string const data = InsetCommand::params2string(p); if (p["target"].empty()) { bv->showDialog("href", data); } else { @@ -1531,7 +1606,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) p["name"] = (cmd.argument().empty()) ? cur.getPossibleLabel() : cmd.argument(); - string const data = InsetCommand::params2string("label", p); + string const data = InsetCommand::params2string(p); if (cmd.argument().empty()) { bv->showDialog("label", data); @@ -1570,16 +1645,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_ERT_INSERT: case LFUN_LISTING_INSERT: case LFUN_MARGINALNOTE_INSERT: - case LFUN_OPTIONAL_INSERT: + case LFUN_ARGUMENT_INSERT: case LFUN_INDEX_INSERT: case LFUN_PREVIEW_INSERT: + case LFUN_SCRIPT_INSERT: // Open the inset, and move the current selection // inside it. doInsertInset(cur, this, cmd, true, true); cur.posForward(); // Some insets are numbered, others are shown in the outline pane so // let's update the labels and the toc backend. - bv->buffer().updateBuffer(); + cur.forceBufferUpdate(); break; case LFUN_TABULAR_INSERT: @@ -1594,16 +1670,19 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FLOAT_INSERT: case LFUN_FLOAT_WIDE_INSERT: case LFUN_WRAP_INSERT: { - // will some text be moved into the inset? - bool content = cur.selection(); + // will some content be moved into the inset? + bool const content = cur.selection(); + // does the content consist of multiple paragraphs? + bool const singlepar = (cur.selBegin().pit() == cur.selEnd().pit()); doInsertInset(cur, this, cmd, true, true); cur.posForward(); - // If some text is moved into the inset, doInsertInset - // puts the cursor outside the inset. To insert the - // caption we put it back into the inset. - if (content) + // If some single-par content is moved into the inset, + // doInsertInset puts the cursor outside the inset. + // To insert the caption we put it back into the inset. + // FIXME cleanup doInsertInset to avoid such dances! + if (content && singlepar) cur.backwardPos(); ParagraphList & pars = cur.text()->paragraphs(); @@ -1633,8 +1712,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // date metrics. FuncRequest cmd_caption(LFUN_CAPTION_INSERT); doInsertInset(cur, cur.text(), cmd_caption, true, false); - bv->buffer().updateBuffer(); - cur.updateFlags(Update::Force); + cur.forceBufferUpdate(); + cur.screenUpdateFlags(Update::Force); // FIXME: When leaving the Float (or Wrap) inset we should // delete any empty paragraph left above or below the // caption. @@ -1647,7 +1726,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) p["symbol"] = bv->cursor().innerText()->getStringToIndex(bv->cursor()); else p["symbol"] = cmd.argument(); - string const data = InsetCommand::params2string("nomenclature", p); + string const data = InsetCommand::params2string(p); bv->showDialog("nomenclature", data); break; } @@ -1658,15 +1737,13 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) p["type"] = from_ascii("idx"); else p["type"] = cmd.argument(); - string const data = InsetCommand::params2string("index_print", p); + string const data = InsetCommand::params2string(p); FuncRequest fr(LFUN_INSET_INSERT, data); dispatch(cur, fr); break; } case LFUN_NOMENCL_PRINT: - case LFUN_TOC_INSERT: - case LFUN_LINE_INSERT: case LFUN_NEWPAGE_INSERT: // do nothing fancy doInsertInset(cur, this, cmd, false, false); @@ -1692,6 +1769,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_MATH_MODE: if (cmd.argument() == "on") // don't pass "on" as argument + // (it would appear literally in the first cell) mathDispatch(cur, FuncRequest(LFUN_MATH_MODE), false); else mathDispatch(cur, cmd, false); @@ -1701,6 +1779,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (cmd.argument().empty()) cur.errorMessage(from_utf8(N_("Missing argument"))); else { + cur.recordUndo(); string s = to_utf8(cmd.argument()); string const s1 = token(s, ' ', 1); int const nargs = s1.empty() ? 0 : convert(s1); @@ -1839,8 +1918,9 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) Language const * lang = languages.getLanguage(to_utf8(cmd.argument())); if (!lang) break; + selectWordWhenUnderCursor(cur, WHOLE_WORD_STRICT); Font font(ignore_font, lang); - toggleAndShow(cur, this, font); + toggleAndShow(cur, this, font, false); break; } @@ -1938,6 +2018,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) if (!cmd.argument().empty()) // FIXME: Are all these characters encoded in one byte in utf8? bv->translateAndInsert(cmd.argument()[0], this, cur); + cur.screenUpdateFlags(Update::FitCursor); break; case LFUN_FLOAT_LIST_INSERT: { @@ -2038,6 +2119,25 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } + case LFUN_SPELLING_REMOVE: { + docstring word = from_utf8(cmd.getArg(0)); + Language * lang; + if (word.empty()) { + word = cur.selectionAsString(false); + // FIXME + if (word.size() > 100 || word.empty()) { + // Get word or selection + selectWordWhenUnderCursor(cur, WHOLE_WORD); + word = cur.selectionAsString(false); + } + lang = const_cast(cur.getFont().language()); + } else + lang = const_cast(languages.getLanguage(cmd.getArg(1))); + WordLangTuple wl(word, lang); + theSpellChecker()->remove(wl); + break; + } + case LFUN_PARAGRAPH_PARAMS_APPLY: { // Given data, an encoding of the ParagraphParameters // generated in the Paragraph dialog, this function sets @@ -2074,26 +2174,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_OUTLINE_UP: outline(OutlineUp, cur); setCursor(cur, cur.pit(), 0); - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); needsUpdate = true; break; case LFUN_OUTLINE_DOWN: outline(OutlineDown, cur); setCursor(cur, cur.pit(), 0); - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); needsUpdate = true; break; case LFUN_OUTLINE_IN: outline(OutlineIn, cur); - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); needsUpdate = true; break; case LFUN_OUTLINE_OUT: outline(OutlineOut, cur); - cur.buffer()->updateBuffer(); + cur.forceBufferUpdate(); needsUpdate = true; break; @@ -2105,12 +2205,27 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= (cur.pos() != cur.lastpos()) && cur.selection(); + if (lyxrc.spellcheck_continuously && !needsUpdate) { + // Check for misspelled text + // The redraw is useful because of the painting of + // misspelled markers depends on the cursor position. + // Trigger a redraw for cursor moves inside misspelled text. + if (!cur.inTexted()) { + // move from regular text to math + needsUpdate = last_misspelled; + } else if (oldTopSlice != cur.top() || oldBoundary != cur.boundary()) { + // move inside regular text + needsUpdate = last_misspelled + || cur.paragraph().isMisspelled(cur.pos(), true); + } + } + // FIXME: The cursor flag is reset two lines below // so we need to check here if some of the LFUN did touch that. // for now only Text::erase() and Text::backspace() do that. // The plan is to verify all the LFUNs and then to remove this // singleParUpdate boolean altogether. - if (cur.result().update() & Update::Force) { + if (cur.result().screenUpdate() & Update::Force) { singleParUpdate = false; needsUpdate = true; } @@ -2121,27 +2236,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // Inserting characters does not change par height in general. So, try // to update _only_ this paragraph. BufferView will detect if a full // metrics update is needed anyway. - cur.updateFlags(Update::SinglePar | Update::FitCursor); + cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); return; } - if (!needsUpdate && &oldTopSlice.inset() == &cur.inset() && oldTopSlice.idx() == cur.idx() - && !sel // sel is a backup of cur.selection() at the beginning of the function. + && !oldSelection // oldSelection is a backup of cur.selection() at the beginning of the function. && !cur.selection()) // FIXME: it would be better if we could just do this // //if (cur.result().update() != Update::FitCursor) - // cur.noUpdate(); + // cur.noScreenUpdate(); // // But some LFUNs do not set Update::FitCursor when needed, so we // do it for all. This is not very harmfull as FitCursor will provoke // a full redraw only if needed but still, a proper review of all LFUN // should be done and this needsUpdate boolean can then be removed. - cur.updateFlags(Update::FitCursor); + cur.screenUpdateFlags(Update::FitCursor); else - cur.updateFlags(Update::Force | Update::FitCursor); + cur.screenUpdateFlags(Update::Force | Update::FitCursor); } @@ -2204,6 +2318,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, code = NOMENCL_PRINT_CODE; else if (cmd.argument() == "label") code = LABEL_CODE; + else if (cmd.argument() == "line") + code = LINE_CODE; else if (cmd.argument() == "note") code = NOTE_CODE; else if (cmd.argument() == "phantom") @@ -2287,8 +2403,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, // make sure we know about such floats if (cit == floats.end() || // and that we know how to generate a list of them - (!cit->second.needsFloatPkg() && cit->second.listCommand().empty())) { - flag.unknown(true); + (!cit->second.usesFloatPkg() && cit->second.listCommand().empty())) { + flag.setUnknown(true); // probably not necessary, but... enable = false; } @@ -2335,17 +2451,16 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_LABEL_INSERT: code = LABEL_CODE; break; - case LFUN_LINE_INSERT: - code = LINE_CODE; - break; case LFUN_INFO_INSERT: code = INFO_CODE; break; - case LFUN_OPTIONAL_INSERT: - code = OPTARG_CODE; - enable = cur.paragraph().insetList().count(OPTARG_CODE) - < cur.paragraph().layout().optionalargs; + case LFUN_ARGUMENT_INSERT: { + code = ARG_CODE; + Layout const & lay = cur.paragraph().layout(); + int const numargs = lay.reqargs + lay.optargs; + enable = cur.paragraph().insetList().count(ARG_CODE) < numargs; break; + } case LFUN_INDEX_INSERT: code = INDEX_CODE; break; @@ -2366,11 +2481,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, // not allowed in description items enable = !inDescriptionItem(cur); break; - case LFUN_TOC_INSERT: - code = TOC_CODE; - // not allowed in description items - enable = !inDescriptionItem(cur); - break; case LFUN_HYPERLINK_INSERT: if (cur.selIsMultiCell() || cur.selIsMultiLine()) { enable = false; @@ -2393,6 +2503,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_PREVIEW_INSERT: code = PREVIEW_CODE; break; + case LFUN_SCRIPT_INSERT: + code = SCRIPT_CODE; + break; case LFUN_MATH_INSERT: case LFUN_MATH_AMS_MATRIX: @@ -2422,38 +2535,38 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_FONT_EMPH: flag.setOnOff(fontinfo.emph() == FONT_ON); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_FONT_ITAL: flag.setOnOff(fontinfo.shape() == ITALIC_SHAPE); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_FONT_NOUN: flag.setOnOff(fontinfo.noun() == FONT_ON); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_FONT_BOLD: case LFUN_FONT_BOLDSYMBOL: flag.setOnOff(fontinfo.series() == BOLD_SERIES); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_FONT_SANS: flag.setOnOff(fontinfo.family() == SANS_FAMILY); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_FONT_ROMAN: flag.setOnOff(fontinfo.family() == ROMAN_FAMILY); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_FONT_TYPEWRITER: flag.setOnOff(fontinfo.family() == TYPEWRITER_FAMILY); - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_CUT: @@ -2497,6 +2610,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, } case LFUN_CLIPBOARD_PASTE: + case LFUN_CLIPBOARD_PASTE_SIMPLE: enable = !theClipboard().empty(); break; @@ -2547,7 +2661,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_TAB_INSERT: case LFUN_TAB_DELETE: - enable = cur.inset().getLayout().isPassThru(); + enable = cur.paragraph().isPassThru(); break; case LFUN_SET_GRAPHICS_GROUP: { @@ -2573,7 +2687,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, } case LFUN_LANGUAGE: - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); flag.setOnOff(to_utf8(cmd.argument()) == cur.real_current_font.language()->lang()); break; @@ -2583,6 +2697,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_SPELLING_ADD: case LFUN_SPELLING_IGNORE: + case LFUN_SPELLING_REMOVE: enable = theSpellChecker(); break; @@ -2624,7 +2739,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_FONT_UWAVE: case LFUN_TEXTSTYLE_APPLY: case LFUN_TEXTSTYLE_UPDATE: - enable = !cur.inset().getLayout().isPassThru(); + enable = !cur.paragraph().isPassThru(); break; case LFUN_WORD_DELETE_FORWARD: @@ -2671,7 +2786,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_LINE_END: case LFUN_CHAR_DELETE_FORWARD: case LFUN_CHAR_DELETE_BACKWARD: - case LFUN_INSET_INSERT: case LFUN_WORD_UPCASE: case LFUN_WORD_LOWCASE: case LFUN_WORD_CAPITALIZE: @@ -2687,6 +2801,19 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, enable = true; break; + case LFUN_INSET_INSERT: { + string const type = cmd.getArg(0); + if (type == "toc") { + code = TOC_CODE; + // not allowed in description items + //FIXME: couldn't this be merged in Inset::insetAllowed()? + enable = !inDescriptionItem(cur); + } else { + enable = true; + } + break; + } + default: return false; }