X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FText3.cpp;h=b5bdc3b4ec0816027853d61ae8722b37fcb9e7dc;hb=1797f5218b8819874f9dbe97b44445b3b5d598a0;hp=c0b88301464511dcd3fd39da94b7216e8a2255c4;hpb=f2c9b56fb4e4abd5183858984dd9329453004c96;p=lyx.git diff --git a/src/Text3.cpp b/src/Text3.cpp index c0b8830146..b5bdc3b4ec 100644 --- a/src/Text3.cpp +++ b/src/Text3.cpp @@ -131,7 +131,9 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) const int old_pos = cur.pos(); #endif cur.insert(new InsetMathHull(hullSimple)); - BOOST_ASSERT(old_pos == cur.pos()); +#ifdef ENABLE_ASSERTIONS + LASSERT(old_pos == cur.pos(), /**/); +#endif cur.nextInset()->edit(cur, true); // don't do that also for LFUN_MATH_MODE // unless you want end up with always changing @@ -154,7 +156,7 @@ static void mathDispatch(Cursor & cur, FuncRequest const & cmd, bool display) { InsetMathHull * formula = new InsetMathHull; istringstream is(to_utf8(sel)); - Lexer lex(0, 0); + Lexer lex; lex.setStream(is); formula->read(lex); if (formula->getType() == hullNone) @@ -284,6 +286,9 @@ static void outline(OutlineOp mode, Cursor & cur) switch (mode) { case OutlineUp: { + if (start == pars.begin()) + // Nothing to move. + return; ParagraphList::iterator dest = start; // Move out (up) from this header if (dest == bgn) @@ -309,7 +314,19 @@ static void outline(OutlineOp mode, Cursor & cur) return; } case OutlineDown: { - ParagraphList::iterator dest = finish; + if (finish == end) + // Nothing to move. + return; + // Go one down from *this* header: + ParagraphList::iterator dest = boost::next(finish, 1); + // Go further down to find header to insert in front of: + for (; dest != end; ++dest) { + toclevel = dest->layout().toclevel; + if (toclevel != Layout::NOT_IN_TOC + && toclevel <= thistoclevel) { + break; + } + } // One such was found: pit_type newpit = distance(bgn, dest); pit_type const len = distance(start, finish); @@ -390,7 +407,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) // at the end? cur.noUpdate(); - BOOST_ASSERT(cur.text() == this); + LASSERT(cur.text() == this, /**/); CursorSlice oldTopSlice = cur.top(); bool oldBoundary = cur.boundary(); bool sel = cur.selection(); @@ -616,16 +633,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_RIGHT: case LFUN_WORD_RIGHT_SELECT: - //FIXME: for visual cursor mode, really move right - if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? - LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + if (lyxrc.visual_cursor) { + needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_RIGHT_SELECT); + needsUpdate |= cursorVisRightOneWord(cur); + if (!needsUpdate && oldTopSlice == cur.top() + && cur.boundary() == oldBoundary) { + cur.undispatched(); + cmd = FuncRequest(LFUN_FINISHED_RIGHT); + } } else { - cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? - LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + if (reverseDirectionNeeded(cur)) { + cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? + LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + } else { + cmd.action = cmd.action == LFUN_WORD_RIGHT_SELECT ? + LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + } + dispatch(cur, cmd); + return; } - dispatch(cur, cmd); - return; + break; case LFUN_WORD_FORWARD: case LFUN_WORD_FORWARD_SELECT: @@ -635,16 +662,26 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_WORD_LEFT: case LFUN_WORD_LEFT_SELECT: - //FIXME: for visual cursor mode, really move left - if (reverseDirectionNeeded(cur)) { - cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? - LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + if (lyxrc.visual_cursor) { + needsUpdate |= cur.selHandle(cmd.action == LFUN_WORD_LEFT_SELECT); + needsUpdate |= cursorVisLeftOneWord(cur); + if (!needsUpdate && oldTopSlice == cur.top() + && cur.boundary() == oldBoundary) { + cur.undispatched(); + cmd = FuncRequest(LFUN_FINISHED_LEFT); + } } else { - cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? - LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + if (reverseDirectionNeeded(cur)) { + cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? + LFUN_WORD_FORWARD_SELECT : LFUN_WORD_FORWARD; + } else { + cmd.action = cmd.action == LFUN_WORD_LEFT_SELECT ? + LFUN_WORD_BACKWARD_SELECT : LFUN_WORD_BACKWARD; + } + dispatch(cur, cmd); + return; } - dispatch(cur, cmd); - return; + break; case LFUN_WORD_BACKWARD: case LFUN_WORD_BACKWARD_SELECT: @@ -658,36 +695,24 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_NEW_LINE: { - // Not allowed by LaTeX (labels or empty par) - if (cur.pos() > cur.paragraph().beginOfBody()) { - // this avoids a double undo - // FIXME: should not be needed, ideally - if (!cur.selection()) - cur.recordUndo(); - cap::replaceSelection(cur); - cur.insert(new InsetNewline); - cur.posForward(); - moveCursor(cur, false); - } + case LFUN_NEWLINE_INSERT: { + InsetNewlineParams inp; + docstring arg = cmd.argument(); + // this avoids a double undo + // FIXME: should not be needed, ideally + if (!cur.selection()) + cur.recordUndo(); + cap::replaceSelection(cur); + if (arg == "linebreak") + inp.kind = InsetNewlineParams::LINEBREAK; + else + inp.kind = InsetNewlineParams::NEWLINE; + cur.insert(new InsetNewline(inp)); + cur.posForward(); + moveCursor(cur, false); break; } - case LFUN_LINE_BREAK: { - // Not allowed by LaTeX (labels or empty par) - if (cur.pos() > cur.paragraph().beginOfBody()) { - // this avoids a double undo - // FIXME: should not be needed, ideally - if (!cur.selection()) - cur.recordUndo(); - cap::replaceSelection(cur); - cur.insert(new InsetLinebreak); - cur.posForward(); - moveCursor(cur, false); - } - break; - } - case LFUN_CHAR_DELETE_FORWARD: if (!cur.selection()) { if (cur.pos() == cur.paragraph().size()) @@ -847,9 +872,23 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) needsUpdate |= dissolveInset(cur); break; - case LFUN_INSET_SETTINGS: - cur.inset().showInsetDialog(bv); + case LFUN_INSET_SETTINGS: { + Inset & inset = cur.inset(); + if (cmd.getArg(0) == insetName(inset.lyxCode())) { + // This inset dialog has been explicitely requested. + inset.showInsetDialog(bv); + break; + } + // else, if there is an inset at the cursor, access this + Inset * next_inset = cur.nextInset(); + if (next_inset) { + next_inset->showInsetDialog(bv); + break; + } + // if not then access the underlying inset. + inset.showInsetDialog(bv); break; + } case LFUN_SPACE_INSERT: if (cur.paragraph().layout().free_spacing) @@ -928,7 +967,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) else if (arg == "linkback") type = Clipboard::LinkBackGraphicsType; else - BOOST_ASSERT(false); + LASSERT(false, /**/); pasteClipboardGraphics(cur, bv->buffer().errorList("Paste"), type); } @@ -968,15 +1007,6 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; } - case LFUN_SERVER_GET_FONT: - if (cur.current_font.fontInfo().shape() == ITALIC_SHAPE) - cur.message(from_ascii("E")); - else if (cur.current_font.fontInfo().shape() == SMALLCAPS_SHAPE) - cur.message(from_ascii("N")); - else - cur.message(from_ascii("0")); - break; - case LFUN_SERVER_GET_LAYOUT: cur.message(cur.paragraph().layout().name()); break; @@ -1126,51 +1156,65 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) break; // Single-click on work area - case LFUN_MOUSE_PRESS: { - // Right click on a footnote flag opens float menu - // FIXME: Why should we clear the selection in this case? - if (cmd.button() == mouse_button::button3) - cur.clearSelection(); - - bool do_selection = cmd.button() == mouse_button::button1 - && cmd.argument() == "region-select"; - // Set the cursor - bool update = bv->mouseSetCursor(cur, do_selection); - - // Insert primary selection with middle mouse - // if there is a local selection in the current buffer, - // insert this - if (cmd.button() == mouse_button::button2) { - if (cap::selection()) { - // Copy the selection buffer to the clipboard - // stack, because we want it to appear in the - // "Edit->Paste recent" menu. - cap::copySelectionToStack(); - - cap::pasteSelection(bv->cursor(), - bv->buffer().errorList("Paste")); - bv->buffer().errors("Paste"); - bv->buffer().markDirty(); - bv->cursor().finishUndo(); - } else { - lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, "paragraph")); + case LFUN_MOUSE_PRESS: + // We are not marking a selection with the keyboard in any case. + cur.bv().cursor().mark() = false; + switch (cmd.button()) { + case mouse_button::button1: + // Set the cursor + if (!bv->mouseSetCursor(cur, cmd.argument() == "region-select")) + cur.updateFlags(Update::SinglePar | Update::FitCursor); + break; + + case mouse_button::button2: + // Middle mouse pasting. + if (!cap::selection()) { + // There is no local selection in the current buffer, so try to + // paste primary selection instead. + lyx::dispatch(FuncRequest(LFUN_PRIMARY_SELECTION_PASTE, + "paragraph")); + // Nothing else to do. + cur.noUpdate(); + return; } - } - - // we have to update after dEPM triggered - if (!update && cmd.button() == mouse_button::button1) { - needsUpdate = false; - cur.noUpdate(); - } + // Copy the selection buffer to the clipboard stack, because we want it + // to appear in the "Edit->Paste recent" menu. + cap::copySelectionToStack(); + cap::pasteSelection(bv->cursor(), bv->buffer().errorList("Paste")); + cur.updateFlags(Update::Force | Update::FitCursor); + bv->buffer().errors("Paste"); + bv->buffer().markDirty(); + bv->cursor().finishUndo(); + break; + case mouse_button::button3: + if (cur.selection()) { + DocIterator const selbeg = cur.selectionBegin(); + DocIterator const selend = cur.selectionEnd(); + Cursor tmpcur = cur; + tm.setCursorFromCoordinates(tmpcur, cmd.x, cmd.y); + // Don't do anything if we right-click a selection, a selection + // context menu should popup instead. + if (tmpcur < selbeg || tmpcur >= selend) { + cur.noUpdate(); + return; + } + } + if (!bv->mouseSetCursor(cur, false)) { + cur.updateFlags(Update::SinglePar | Update::FitCursor); + break; + } + default: + break; + } // switch (cmd.button()) break; - } case LFUN_MOUSE_MOTION: { - // Only use motion with button 1 - //if (cmd.button() != mouse_button::button1) - // return false; - + // Mouse motion with right or middle mouse do nothing for now. + if (cmd.button() != mouse_button::button1) { + cur.noUpdate(); + return; + } // ignore motions deeper nested than the real anchor Cursor & bvcur = cur.bv().cursor(); if (!bvcur.anchor_.hasPart(cur)) { @@ -1195,42 +1239,52 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) else if (cmd.y < 0) lyx::dispatch(FuncRequest(LFUN_UP_SELECT)); } - - if (cur.top() == old) - cur.noUpdate(); - else { - // FIXME: This is brute force! But without it the selected - // area is not corrected updated while moving the mouse. - cur.updateFlags(Update::Force | Update::FitCursor); - // don't set anchor_ - bvcur.setCursor(cur); - bvcur.selection() = true; - //lyxerr << "MOTION: " << bv->cursor() << endl; + // We continue with our existing selection or start a new one, so don't + // reset the anchor. + bvcur.setCursor(cur); + bvcur.selection() = 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(); + return; } break; } - case LFUN_MOUSE_RELEASE: { - if (cmd.button() == mouse_button::button2) - break; - - if (cmd.button() == mouse_button::button1) { - // if there is new selection, update persistent - // selection, otherwise, single click does not - // clear persistent selection buffer + case LFUN_MOUSE_RELEASE: + switch (cmd.button()) { + case mouse_button::button1: + // Cursor was set at LFUN_MOUSE_PRESS or LFUN_MOUSE_MOTION time. + // If there is a new selection, update persistent selection; + // otherwise, single click does not clear persistent selection + // buffer. if (cur.selection()) { - // finish selection - // if double click, cur is moved to the end of word by selectWord - // but bvcur is current mouse position - Cursor & bvcur = cur.bv().cursor(); - bvcur.selection() = true; + // Finish selection. + // If double click, cur is moved to the end of word by selectWord + // but bvcur is current mouse position. + cur.bv().cursor().selection() = true; } - needsUpdate = false; + // FIXME: We could try to handle drag and drop of selection here. cur.noUpdate(); - } + return; + + case mouse_button::button2: + // Middle mouse pasting is handled at mouse press time, + // see LFUN_MOUSE_PRESS. + cur.noUpdate(); + 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(); + return; + + } // switch (cmd.button()) break; - } case LFUN_SELF_INSERT: { if (cmd.argument().empty()) @@ -1267,7 +1321,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) } p["target"] = (cmd.argument().empty()) ? content : cmd.argument(); - string const data = InsetCommandMailer::params2string("href", p); + string const data = InsetCommand::params2string("href", p); if (p["target"].empty()) { bv->showDialog("href", data); } else { @@ -1283,7 +1337,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) p["name"] = (cmd.argument().empty()) ? cur.getPossibleLabel() : cmd.argument(); - string const data = InsetCommandMailer::params2string("label", p); + string const data = InsetCommand::params2string("label", p); if (cmd.argument().empty()) { bv->showDialog("label", data); @@ -1408,12 +1462,8 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) case LFUN_INDEX_PRINT: case LFUN_NOMENCL_PRINT: case LFUN_TOC_INSERT: - case LFUN_HFILL_INSERT: case LFUN_LINE_INSERT: case LFUN_NEWPAGE_INSERT: - case LFUN_PAGEBREAK_INSERT: - case LFUN_CLEARPAGE_INSERT: - case LFUN_CLEARDOUBLEPAGE_INSERT: // do nothing fancy doInsertInset(cur, this, cmd, false, false); cur.posForward(); @@ -1471,7 +1521,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) cap::replaceSelection(cur); cur.insert(new InsetMathHull(hullSimple)); checkAndActivateInset(cur, true); - BOOST_ASSERT(cur.inMathed()); + LASSERT(cur.inMathed(), /**/); cur.dispatch(cmd); break; } @@ -1657,11 +1707,17 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) breakParagraph(cur); } - //FIXME Check if this should be emptyLayout() - setLayout(cur, tclass.defaultLayoutName()); + docstring const laystr = cur.inset().useEmptyLayout() ? + tclass.emptyLayoutName() : + tclass.defaultLayoutName(); + setLayout(cur, laystr); ParagraphParameters p; setParagraphs(cur, p); - insertInset(cur, new InsetFloatList(to_utf8(cmd.argument()))); + // FIXME This should be simplified when InsetFloatList takes a + // Buffer in its constructor. + InsetFloatList * ifl = new InsetFloatList(to_utf8(cmd.argument())); + ifl->setBuffer(bv->buffer()); + insertInset(cur, ifl); cur.posForward(); } else { lyxerr << "Non-existent float type: " @@ -1805,7 +1861,7 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, FuncStatus & flag) const { - BOOST_ASSERT(cur.text() == this); + LASSERT(cur.text() == this, /**/); Font const & font = cur.real_current_font; FontInfo const & fontinfo = font.fontInfo(); @@ -1864,6 +1920,8 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, code = NOTE_CODE; else if (cmd.argument() == "ref") code = REF_CODE; + else if (cmd.argument() == "space") + code = SPACE_CODE; else if (cmd.argument() == "toc") code = TOC_CODE; else if (cmd.argument() == "vspace") @@ -1878,7 +1936,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, code = ERT_CODE; break; case LFUN_LISTING_INSERT: - code = LISTINGS_CODE; + code = LISTINGS_CODE; break; case LFUN_FOOTNOTE_INSERT: code = FOOT_CODE; @@ -1909,6 +1967,9 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, break; case LFUN_NOTE_INSERT: code = NOTE_CODE; + // in commands (sections etc., only Notes are allowed) + enable = (cmd.argument().empty() || cmd.getArg(0) == "Note" || + !cur.paragraph().layout().isCommand()); break; case LFUN_FLEX_INSERT: { code = FLEX_CODE; @@ -1966,7 +2027,6 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, // always allow this, since we will inset a raw quote // if an inset is not allowed. break; - case LFUN_HFILL_INSERT: case LFUN_SPECIALCHAR_INSERT: code = SPECIALCHAR_CODE; break; @@ -2090,6 +2150,11 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, enable = (cur.paragraph().layout().toclevel != Layout::NOT_IN_TOC); break; + case LFUN_NEWLINE_INSERT: + // LaTeX restrictions (labels or empty par) + enable = (cur.pos() > cur.paragraph().beginOfBody()); + break; + case LFUN_WORD_DELETE_FORWARD: case LFUN_WORD_DELETE_BACKWARD: case LFUN_LINE_DELETE: @@ -2121,9 +2186,7 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_PARAGRAPH_UP: case LFUN_PARAGRAPH_DOWN: case LFUN_LINE_BEGIN: - case LFUN_LINE_BREAK: case LFUN_LINE_END: - case LFUN_NEW_LINE: case LFUN_CHAR_DELETE_FORWARD: case LFUN_DELETE_FORWARD_SKIP: case LFUN_CHAR_DELETE_BACKWARD: @@ -2138,16 +2201,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_CHARS_TRANSPOSE: case LFUN_SERVER_GET_XY: case LFUN_SERVER_SET_XY: - case LFUN_SERVER_GET_FONT: case LFUN_SERVER_GET_LAYOUT: case LFUN_LAYOUT: case LFUN_DATE_INSERT: case LFUN_SELF_INSERT: case LFUN_LINE_INSERT: case LFUN_NEWPAGE_INSERT: - case LFUN_PAGEBREAK_INSERT: - case LFUN_CLEARPAGE_INSERT: - case LFUN_CLEARDOUBLEPAGE_INSERT: case LFUN_MATH_DISPLAY: case LFUN_MATH_IMPORT_SELECTION: case LFUN_MATH_MODE: