X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FText3.cpp;h=f871bb31d157c1b1a91371428be779b2774ebb21;hb=809a063358ba6ee5ca2be27be111b0d605e0d723;hp=5e9f6cff38b20571b40248fab1788bac76129458;hpb=5d269df60674df4b8f5f56cdf4e16c88f23df32b;p=features.git diff --git a/src/Text3.cpp b/src/Text3.cpp index 5e9f6cff38..f871bb31d1 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -118,6 +118,11 @@ static void toggleAndShow(Cursor & cur, Text * text, cur.real_current_font)) text->setCursor(cur, cur.pit(), cur.pos(), false, !cur.boundary()); + if (font.language() != ignore_language) + // We need a buffer update if we change the language + // (e.g., with info insets or if the selection contains + // a par label) + cur.forceBufferUpdate(); } } @@ -238,7 +243,8 @@ static void ipaChar(Cursor & cur, InsetIPAChar::Kind kind) static bool doInsertInset(Cursor & cur, Text * text, - FuncRequest const & cmd, bool edit, bool pastesel) + FuncRequest const & cmd, bool edit, + bool pastesel, bool resetfont = false) { Buffer & buffer = cur.bv().buffer(); BufferParams const & bparams = buffer.params(); @@ -252,7 +258,7 @@ static bool doInsertInset(Cursor & cur, Text * text, cur.recordUndo(); if (cmd.action() == LFUN_ARGUMENT_INSERT) { bool cotextinsert = false; - InsetArgument const * const ia = static_cast(inset); + InsetArgument * const ia = static_cast(inset); Layout const & lay = cur.paragraph().layout(); Layout::LaTeXArgMap args = lay.args(); Layout::LaTeXArgMap::const_iterator const lait = args.find(ia->name()); @@ -275,6 +281,7 @@ static bool doInsertInset(Cursor & cur, Text * text, else ds = cur.paragraph().asString(); text->insertInset(cur, inset); + ia->init(cur.paragraph()); if (edit) inset->edit(cur, true); // Now put co-text into inset @@ -298,8 +305,11 @@ static bool doInsertInset(Cursor & cur, Text * text, * paragraph and the inset allows setting layout * FIXME: this does not work as expected when change tracking is on * However, we do not really know what to do in this case. + * FIXME: figure out a good test in the environment case (see #12251). */ - if (cur.paragraph().empty() && !inset->forcePlainLayout()) { + if (cur.paragraph().layout().isCommand() + && cur.paragraph().empty() + && !inset->forcePlainLayout()) { cur.paragraph().setPlainOrDefaultLayout(bparams.documentClass()); move_layout = true; } @@ -313,6 +323,19 @@ static bool doInsertInset(Cursor & cur, Text * text, } text->insertInset(cur, inset); + InsetText * inset_text = inset->asInsetText(); + if (inset_text) { + Font const & font = inset->inheritFont() + ? cur.bv().textMetrics(text).displayFont(cur.pit(), cur.pos()) + : bparams.getFont(); + inset_text->setOuterFont(cur.bv(), font.fontInfo()); + } + + if (cmd.action() == LFUN_ARGUMENT_INSERT) { + InsetArgument * const ia = static_cast(inset); + ia->init(cur.paragraph()); + } + if (edit) inset->edit(cur, true); @@ -323,8 +346,14 @@ static bool doInsertInset(Cursor & cur, Text * text, cur.buffer()->errors("Paste"); cur.clearSelection(); // bug 393 cur.finishUndo(); - InsetText * inset_text = inset->asInsetText(); if (inset_text) { + if (resetfont) { + // Reset of font (not language) is requested. + // Used by InsetIndex (#11961). + Language const * lang = cur.getFont().language(); + Font font(bparams.getFont().fontInfo(), lang); + cur.paragraph().resetFonts(font); + } inset_text->fixParagraphsFont(); cur.pos() = 0; cur.pit() = 0; @@ -787,24 +816,20 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bool const cur_moved = cursorForward(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && 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(); - } + // we will be moving out the inset, so we should execute + // the depm-mechanism. + // 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(); } break; } @@ -816,24 +841,21 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bool const cur_moved = cursorBackward(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && 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(); - } + // we will be moving out the inset, so we should execute + // the depm-mechanism. + // 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(); } break; } @@ -844,8 +866,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cur.selHandle(act == LFUN_CHAR_LEFT_SELECT); bool const cur_moved = cursorVisLeft(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { cur.undispatched(); cmd = FuncRequest(LFUN_FINISHED_LEFT); } @@ -868,8 +890,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cur.selHandle(cmd.action() == LFUN_CHAR_RIGHT_SELECT); bool const cur_moved = cursorVisRight(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { cur.undispatched(); cmd = FuncRequest(LFUN_FINISHED_RIGHT); } @@ -892,14 +914,12 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_UP: case LFUN_DOWN: { // stop/start the selection - bool select = cmd.action() == LFUN_DOWN_SELECT || - cmd.action() == LFUN_UP_SELECT; - + bool const select = cmd.action() == LFUN_DOWN_SELECT + || cmd.action() == LFUN_UP_SELECT; // move cursor up/down - bool up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP; - bool const atFirstOrLastRow = cur.atFirstOrLastRow(up); + bool const up = cmd.action() == LFUN_UP_SELECT || cmd.action() == LFUN_UP; - if (!atFirstOrLastRow) { + if (!cur.atFirstOrLastRow(up)) { needsUpdate |= cur.selHandle(select); cur.upDownInText(up, needsUpdate); needsUpdate |= cur.beforeDispatchCursor().inMathed(); @@ -915,13 +935,35 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) cur.forceBufferUpdate(); break; } + needsUpdate |= cur.selHandle(select); + bool const can_move = cur.upDownInText(up, needsUpdate); + // if the cursor can be moved up or down at an upper level, + // delegate the dispatch to next level. Otherwise, we are + // done. + if (can_move) { + cmd = FuncRequest(up ? LFUN_FINISHED_UP : LFUN_FINISHED_DOWN); + cur.undispatched(); + } + } - // if the cursor cannot be moved up or down do not remove - // the selection right now, but wait for the next dispatch. - if (select) - needsUpdate |= cur.selHandle(select); + break; + } + + case LFUN_FINISHED_UP: + case LFUN_FINISHED_DOWN: { + // move cursor up/down + bool const up = cmd.action() == LFUN_FINISHED_UP; + + if (!cur.atFirstOrLastRow(up)) { cur.upDownInText(up, needsUpdate); - cur.undispatched(); + needsUpdate |= cur.beforeDispatchCursor().inMathed(); + } else { + bool const can_move = cur.upDownInText(up, needsUpdate); + // if the cursor can be moved up or down and we are not + // moving cusor at top level, wait for the next dispatch. + // Otherwise, we are done. + if (can_move) + cur.undispatched(); } break; @@ -1002,8 +1044,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_RIGHT_SELECT); bool const cur_moved = cursorVisRightOneWord(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { cur.undispatched(); cmd = FuncRequest(LFUN_FINISHED_RIGHT); } @@ -1026,24 +1068,20 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bool const cur_moved = cursorForwardOneWord(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && 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(); - } + // we will be moving out the inset, so we should execute + // the depm-mechanism. + // 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(); } break; } @@ -1054,8 +1092,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= cur.selHandle(cmd.action() == LFUN_WORD_LEFT_SELECT); bool const cur_moved = cursorVisLeftOneWord(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && oldTopSlice == cur.top() && cur.boundary() == oldBoundary) { cur.undispatched(); cmd = FuncRequest(LFUN_FINISHED_LEFT); } @@ -1078,25 +1116,21 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bool const cur_moved = cursorBackwardOneWord(cur); needsUpdate |= cur_moved; - if (!cur_moved && oldTopSlice == cur.top() - && cur.boundary() == oldBoundary) { + if (!cur_moved && cur.depth() > 1 + && 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(); - } + // we will be moving out the inset, so we should execute + // the depm-mechanism. + // 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(); } break; } @@ -1503,7 +1537,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) pasteFromStack(cur, bv->buffer().errorList("Paste"), 0); else if (theClipboard().hasTextContents()) { if (pasteClipboardText(cur, bv->buffer().errorList("Paste"), - true, Clipboard::AnyTextType)) + !cur.paragraph().parbreakIsNewline(), + Clipboard::AnyTextType)) tryGraphics = false; } if (tryGraphics && theClipboard().hasGraphicsContents()) @@ -1839,8 +1874,18 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bvcur.resetAnchor(); if (!bv->mouseSetCursor(cur, cmd.modifier() == ShiftModifier)) cur.screenUpdateFlags(Update::SinglePar | Update::FitCursor); - if (bvcur.wordSelection()) - selectWord(bvcur, WHOLE_WORD); + // FIXME: move this to mouseSetCursor? + if (bvcur.wordSelection() && bvcur.inTexted()) { + // select word around new position + Cursor c = bvcur; + c.selection(false); + c.text()->selectWord(c, WHOLE_WORD); + // use the correct word boundary, depending on selection direction + if (bvcur.top() > bvcur.normalAnchor()) + bvcur.pos() = c.selEnd().pos(); + else + bvcur.pos() = c.selBegin().pos(); + } break; case mouse_button::button2: @@ -2078,22 +2123,19 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_INDEX_INSERT: case LFUN_PREVIEW_INSERT: case LFUN_SCRIPT_INSERT: - case LFUN_IPA_INSERT: + case LFUN_IPA_INSERT: { + // Indexes reset font formatting (#11961) + bool const resetfont = cmd.action() == LFUN_INDEX_INSERT; // Open the inset, and move the current selection // inside it. - doInsertInset(cur, this, cmd, true, true); + doInsertInset(cur, this, cmd, true, true, resetfont); cur.posForward(); - /* The font of the inset is computed in metrics(), and this is - * used to compute the height of the caret (because the font - * is stored in TextMetrics::font_). When we insert, we have - * to make sure that metrics are computed so that the caret - * height is correct. Arguably, this is hackish.*/ - bv->processUpdateFlags(Update::SinglePar); cur.setCurrentFont(); // Some insets are numbered, others are shown in the outline pane so // let's update the labels and the toc backend. cur.forceBufferUpdate(); break; + } case LFUN_FLEX_INSERT: { // Open the inset, and move the current selection @@ -2116,6 +2158,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // leave this now in order to insert the next one. if (inautoarg) { cur.leaveInset(cur.inset()); + cur.setCurrentFont(); cur.posForward(); if (arg.insertonnewline && cur.pos() > 0) { FuncRequest cmd2(LFUN_PARAGRAPH_BREAK); @@ -2503,10 +2546,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) selectWordWhenUnderCursor(cur, WHOLE_WORD_STRICT); Font font(ignore_font, lang); toggleAndShow(cur, this, font, toggle); - // We need a buffer update if we change the language - // of an info inset - if (cur.insetInSelection(INFO_CODE)) - cur.forceBufferUpdate(); break; } @@ -2541,10 +2580,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) freeFonts.push(make_pair(props, font)); toggleall = toggle; toggleAndShow(cur, this, font, toggleall); - // We need a buffer update if we change the language - // of an info inset - if (cur.insetInSelection(INFO_CODE)) - cur.forceBufferUpdate(); cur.message(bformat(_("Text properties applied: %1$s"), props)); } else LYXERR0("Invalid argument of textstyle-update"); @@ -2732,6 +2767,30 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } case LFUN_SPELLING_ADD_LOCAL: { + Language const * language = getLanguage(cur, cmd.getArg(1)); + docstring word = from_utf8(cmd.getArg(0)); + if (word.empty()) { + word = cur.selectionAsString(false); + if (word.size() > 100) + break; + if (word.empty()) { + // Get word or selection + selectWordWhenUnderCursor(cur, WHOLE_WORD); + word = cur.selectionAsString(false); + } + } + WordLangTuple wl(word, language); + if (!bv->buffer().params().spellignored(wl)) { + cur.recordUndoBufferParams(); + bv->buffer().params().spellignore().push_back(wl); + cur.recordUndo(); + // trigger re-check of whole buffer + bv->buffer().requestSpellcheck(); + } + break; + } + + case LFUN_SPELLING_REMOVE_LOCAL: { Language const * language = getLanguage(cur, cmd.getArg(1)); docstring word = from_utf8(cmd.getArg(0)); if (word.empty()) { @@ -2746,9 +2805,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } WordLangTuple wl(word, language); bool has_item = false; - vector il = bv->buffer().params().spellignore(); - vector::const_iterator it = il.begin(); - for (; it != il.end(); ++it) { + vector::const_iterator it = bv->buffer().params().spellignore().begin(); + for (; it != bv->buffer().params().spellignore().end(); ++it) { if (it->lang()->code() != wl.lang()->code()) continue; if (it->word() == wl.word()) { @@ -2756,21 +2814,16 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } } - if (!has_item) { + if (has_item) { cur.recordUndoBufferParams(); - bv->buffer().params().spellignore().push_back(wl); + bv->buffer().params().spellignore().erase(it); cur.recordUndo(); - // trigger re-check - WordLangTuple wl; - docstring_list suggestions; - Paragraph const & par = cur.paragraph(); - pos_type from = cur.pos(); - pos_type to = from; - par.spellCheck(from, to, wl, suggestions, true, true); + // trigger re-check of whole buffer + bv->buffer().requestSpellcheck(); } break; } - + case LFUN_SPELLING_IGNORE: { Language const * language = getLanguage(cur, cmd.getArg(1)); @@ -2998,6 +3051,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, code = BRANCH_CODE; else if (cmd.argument() == "citation") code = CITE_CODE; + else if (cmd.argument() == "counter") + code = COUNTER_CODE; else if (cmd.argument() == "ert") code = ERT_CODE; else if (cmd.argument() == "external") @@ -3397,6 +3452,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, break; case LFUN_PRIMARY_SELECTION_PASTE: + status.setUnknown(!theSelection().supported()); enable = cur.selection() || !theSelection().empty(); break; @@ -3502,6 +3558,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_SPELLING_ADD: case LFUN_SPELLING_ADD_LOCAL: + case LFUN_SPELLING_REMOVE_LOCAL: case LFUN_SPELLING_IGNORE: case LFUN_SPELLING_REMOVE: enable = theSpellChecker() != nullptr;