X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext3.C;h=007e0ab6e066d463e24fcf184c1c0748d03d7714;hb=38fd440edb31b117678c0dda76b3a58dfe182ed2;hp=2a7c3ec47d57f34de61f3cd643b7c82bb0835a89;hpb=c69f29dda75751987a71ec3dccc9b62725006e20;p=lyx.git diff --git a/src/text3.C b/src/text3.C index 2a7c3ec47d..007e0ab6e0 100644 --- a/src/text3.C +++ b/src/text3.C @@ -22,11 +22,212 @@ #include "ParagraphParameters.h" #include "gettext.h" #include "intl.h" +#include "language.h" #include "support/lstrings.h" #include "frontends/LyXView.h" +#include "frontends/screen.h" #include "frontends/WorkArea.h" #include "insets/insetspecialchar.h" #include "insets/insettext.h" +#include "insets/insetquotes.h" +#include "insets/insetcommand.h" +#include "undo_funcs.h" + +#include +#include + +using std::endl; + +extern string current_layout; + +namespace { + + void finishChange(BufferView * bv, bool fitcur = false) + { + finishUndo(); + bv->moveCursorUpdate(fitcur); + bv->owner()->view_state_changed(); + } + +} + + +bool LyXText::gotoNextInset(BufferView * bv, + vector const & codes, string const & contents) const +{ + LyXCursor res = cursor; + Inset * inset; + do { + if (res.pos() < res.par()->size() - 1) { + res.pos(res.pos() + 1); + } else { + res.par(res.par()->next()); + res.pos(0); + } + + } while (res.par() && + !(res.par()->isInset(res.pos()) + && (inset = res.par()->getInset(res.pos())) != 0 + && find(codes.begin(), codes.end(), inset->lyxCode()) + != codes.end() + && (contents.empty() || + static_cast( + res.par()->getInset(res.pos()))->getContents() + == contents))); + + if (res.par()) { + setCursor(bv, res.par(), res.pos(), false); + return true; + } + return false; +} + + +void LyXText::gotoInset(BufferView * bv, vector const & codes, + bool same_content) +{ + bv->hideCursor(); + bv->beforeChange(this); + update(bv, false); + + string contents; + if (same_content && cursor.par()->isInset(cursor.pos())) { + Inset const * inset = cursor.par()->getInset(cursor.pos()); + if (find(codes.begin(), codes.end(), inset->lyxCode()) + != codes.end()) + contents = static_cast(inset)->getContents(); + } + + if (!gotoNextInset(bv, codes, contents)) { + if (cursor.pos() || cursor.par() != ownerParagraph()) { + LyXCursor tmp = cursor; + cursor.par(ownerParagraph()); + cursor.pos(0); + if (!gotoNextInset(bv, codes, contents)) { + cursor = tmp; + bv->owner()->message(_("No more insets")); + } + } else { + bv->owner()->message(_("No more insets")); + } + } + update(bv, false); + selection.cursor = cursor; +} + + +void LyXText::gotoInset(BufferView * bv, Inset::Code code, bool same_content) +{ + gotoInset(bv, vector(1, code), same_content); +} + + +void LyXText::cursorPrevious(BufferView * bv) +{ + if (!cursor.row()->previous()) { + if (first_y > 0) { + int new_y = bv->text->first_y - bv->workarea().workHeight(); + bv->screen().draw(bv->text, bv, new_y < 0 ? 0 : new_y); + bv->updateScrollbar(); + } + return; + } + + int y = first_y; + Row * cursorrow = cursor.row(); + + setCursorFromCoordinates(bv, cursor.x_fix(), y); + finishUndo(); + + int new_y; + if (cursorrow == bv->text->cursor.row()) { + // we have a row which is higher than the workarea so we leave the + // cursor on the start of the row and move only the draw up as soon + // as we move the cursor or do something while inside the row (it may + // span several workarea-heights) we'll move to the top again, but this + // is better than just jump down and only display part of the row. + new_y = bv->text->first_y - bv->workarea().workHeight(); + } else { + if (inset_owner) { + new_y = bv->text->cursor.iy() + + bv->theLockingInset()->insetInInsetY() + y + + cursor.row()->height() + - bv->workarea().workHeight() + 1; + } else { + new_y = cursor.y() + - cursor.row()->baseline() + + cursor.row()->height() + - bv->workarea().workHeight() + 1; + } + } + bv->screen().draw(bv->text, bv, new_y < 0 ? 0 : new_y); + if (cursor.row()->previous()) { + LyXCursor cur; + setCursor(bv, cur, cursor.row()->previous()->par(), + cursor.row()->previous()->pos(), false); + if (cur.y() > first_y) { + cursorUp(bv, true); + } + } + bv->updateScrollbar(); +} + + +void LyXText::cursorNext(BufferView * bv) +{ + if (!cursor.row()->next()) { + int y = cursor.y() - cursor.row()->baseline() + + cursor.row()->height(); + if (y > int(first_y + bv->workarea().workHeight())) { + bv->screen().draw(bv->text, bv, + bv->text->first_y + bv->workarea().workHeight()); + bv->updateScrollbar(); + } + return; + } + + int y = first_y + bv->workarea().workHeight(); + if (inset_owner && !first_y) { + y -= (bv->text->cursor.iy() + - bv->text->first_y + + bv->theLockingInset()->insetInInsetY()); + } + + getRowNearY(y); + + Row * cursorrow = cursor.row(); + setCursorFromCoordinates(bv, cursor.x_fix(), y); + // + workarea().workHeight()); + finishUndo(); + + int new_y; + if (cursorrow == bv->text->cursor.row()) { + // we have a row which is higher than the workarea so we leave the + // cursor on the start of the row and move only the draw down as soon + // as we move the cursor or do something while inside the row (it may + // span several workarea-heights) we'll move to the top again, but this + // is better than just jump down and only display part of the row. + new_y = bv->text->first_y + bv->workarea().workHeight(); + } else { + if (inset_owner) { + new_y = bv->text->cursor.iy() + + bv->theLockingInset()->insetInInsetY() + + y - cursor.row()->baseline(); + } else { + new_y = cursor.y() - cursor.row()->baseline(); + } + } + bv->screen().draw(bv->text, bv, new_y); + if (cursor.row()->next()) { + LyXCursor cur; + setCursor(bv, cur, cursor.row()->next()->par(), + cursor.row()->next()->pos(), false); + if (cur.y() < int(first_y + bv->workarea().workHeight())) { + cursorDown(bv, true); + } + } + bv->updateScrollbar(); +} void LyXText::update(BufferView * bv, bool changed) @@ -53,6 +254,9 @@ void specialChar(LyXText * lt, BufferView * bv, InsetSpecialChar::Kind kind) Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) { + lyxerr[Debug::ACTION] << "LyXFunc::dispatch: action[" << cmd.action + <<"] arg[" << cmd.argument << "]" << endl; + BufferView * bv = cmd.view(); switch (cmd.action) { @@ -75,7 +279,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) updateCounters(cmd.view()); setCursor(cmd.view(), cursor.par(), cursor.pos()); update(bv); - return Inset::DISPATCHED; + break; } case LFUN_DELETE_WORD_FORWARD: @@ -83,24 +287,24 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv, false); deleteWordForward(bv); update(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_DELETE_WORD_BACKWARD: bv->beforeChange(this); update(bv, false); deleteWordBackward(bv); update(bv, true); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_DELETE_LINE_FORWARD: bv->beforeChange(this); update(bv, false); deleteLineForward(bv); update(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_SHIFT_TAB: case LFUN_TAB: @@ -108,10 +312,10 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); update(bv, false); cursorTab(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; - case LFUN_WORDRIGHT: + case LFUN_WORDRIGHT: if (!selection.mark()) bv->beforeChange(this); update(bv, false); @@ -119,8 +323,8 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeftOneWord(bv); else cursorRightOneWord(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_WORDLEFT: if (!selection.mark()) @@ -130,24 +334,24 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorRightOneWord(bv); else cursorLeftOneWord(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_BEGINNINGBUF: if (!selection.mark()) bv->beforeChange(this); update(bv, false); cursorTop(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_ENDBUF: if (selection.mark()) bv->beforeChange(this); update(bv, false); cursorBottom(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_RIGHTSEL: update(bv, false); @@ -155,8 +359,8 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeft(bv); else cursorRight(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_LEFTSEL: update(bv, false); @@ -164,56 +368,56 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorRight(bv); else cursorLeft(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_UPSEL: update(bv, false); cursorUp(bv, true); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_DOWNSEL: update(bv, false); cursorDown(bv, true); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_UP_PARAGRAPHSEL: update(bv, false); cursorUpParagraph(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_DOWN_PARAGRAPHSEL: update(bv, false); cursorDownParagraph(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_PRIORSEL: update(bv, false); - bv->cursorPrevious(this); - bv->finishChange(true); - return Inset::DISPATCHED; + cursorPrevious(bv); + finishChange(bv, true); + break; case LFUN_NEXTSEL: update(bv, false); - bv->cursorNext(this); - bv->finishChange(); - return Inset::DISPATCHED; + cursorNext(bv); + finishChange(bv, true); + break; case LFUN_HOMESEL: update(bv, false); cursorHome(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_ENDSEL: update(bv, false); cursorEnd(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_WORDRIGHTSEL: update(bv, false); @@ -221,8 +425,8 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeftOneWord(bv); else cursorRightOneWord(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_WORDLEFTSEL: update(bv, false); @@ -230,8 +434,8 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorRightOneWord(bv); else cursorLeftOneWord(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_RIGHT: { bool is_rtl = cursor.par()->isRightToLeftPar(bv->buffer()->params); @@ -245,16 +449,13 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) && isHighlyEditableInset(cursor.par()->getInset(cursor.pos()))) { Inset * tmpinset = cursor.par()->getInset(cursor.pos()); cmd.message(tmpinset->editMessage()); - if (is_rtl) - tmpinset->edit(bv, false); - else - tmpinset->edit(bv); - return Inset::DISPATCHED; + tmpinset->edit(bv, !is_rtl); + break; } if (!is_rtl) cursorRight(bv, false); - bv->finishChange(false); - return Inset::DISPATCHED; + finishChange(bv); + break; } case LFUN_LEFT: { @@ -273,17 +474,13 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) isHighlyEditableInset(cursor.par()->getInset(cursor.pos()))) { Inset * tmpinset = cursor.par()->getInset(cursor.pos()); cmd.message(tmpinset->editMessage()); - if (is_rtl) - tmpinset->edit(bv); - else - tmpinset->edit(bv, false); + tmpinset->edit(bv, is_rtl); break; - return Inset::DISPATCHED; } if (is_rtl) cursorRight(bv, false); - bv->finishChange(false); - return Inset::DISPATCHED; + finishChange(bv); + break; } case LFUN_UP: @@ -291,68 +488,68 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorUp(bv); - bv->finishChange(false); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_DOWN: if (!selection.mark()) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorDown(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_UP_PARAGRAPH: if (!selection.mark()) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorUpParagraph(bv); - bv->finishChange(); - return Inset::DISPATCHED; + finishChange(bv); + break; case LFUN_DOWN_PARAGRAPH: if (!selection.mark()) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorDownParagraph(bv); - bv->finishChange(false); - return Inset::DISPATCHED; + finishChange(bv, false); + break; case LFUN_PRIOR: if (!selection.mark()) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); - bv->cursorPrevious(this); - bv->finishChange(false); + cursorPrevious(bv); + finishChange(bv, false); // was: // finishUndo(); // moveCursorUpdate(false, false); // owner_->view_state_changed(); - return Inset::DISPATCHED; + break; case LFUN_NEXT: if (!selection.mark()) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); - bv->cursorNext(this); - bv->finishChange(false); - return Inset::DISPATCHED; + cursorNext(bv); + finishChange(bv, false); + break; case LFUN_HOME: if (!selection.mark()) bv->beforeChange(this); update(bv); cursorHome(bv); - bv->finishChange(false); - return Inset::DISPATCHED; + finishChange(bv, false); + break; case LFUN_END: if (!selection.mark()) bv->beforeChange(this); update(bv); cursorEnd(bv); - bv->finishChange(false); - return Inset::DISPATCHED; + finishChange(bv, false); + break; case LFUN_BREAKLINE: bv->beforeChange(this); @@ -360,7 +557,210 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv, true); setCursor(bv, cursor.par(), cursor.pos()); bv->moveCursorUpdate(false); - return Inset::DISPATCHED; + break; + + case LFUN_DELETE: + if (!selection.set()) { + Delete(bv); + selection.cursor = cursor; + update(bv); + // It is possible to make it a lot faster still + // just comment out the line below... + bv->showCursor(); + } else { + update(bv, false); + cutSelection(bv, true); + update(bv); + } + bv->moveCursorUpdate(false); + bv->owner()->view_state_changed(); + bv->switchKeyMap(); + break; + + case LFUN_DELETE_SKIP: + // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP. + if (!selection.set()) { + LyXCursor cur = cursor; + if (cur.pos() == cur.par()->size()) { + cursorRight(bv); + cur = cursor; + if (cur.pos() == 0 + && !(cur.par()->params().spaceTop() + == VSpace (VSpace::NONE))) { + setParagraph(bv, + cur.par()->params().lineTop(), + cur.par()->params().lineBottom(), + cur.par()->params().pagebreakTop(), + cur.par()->params().pagebreakBottom(), + VSpace(VSpace::NONE), + cur.par()->params().spaceBottom(), + cur.par()->params().spacing(), + cur.par()->params().align(), + cur.par()->params().labelWidthString(), 0); + cursorLeft(bv); + update(bv); + } else { + cursorLeft(bv); + Delete(bv); + selection.cursor = cursor; + } + } else { + Delete(bv); + selection.cursor = cursor; + } + } else { + update(bv, false); + cutSelection(bv, true); + } + update(bv); + break; + + + case LFUN_BACKSPACE: + if (!selection.set()) { + if (bv->owner()->getIntl().getTransManager().backspace()) { + backspace(bv); + selection.cursor = cursor; + update(bv); + // It is possible to make it a lot faster still + // just comment out the line below... + bv->showCursor(); + } + } else { + update(bv, false); + cutSelection(bv, true); + update(bv); + } + bv->owner()->view_state_changed(); + bv->switchKeyMap(); + break; + + case LFUN_BACKSPACE_SKIP: + // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP. + if (!selection.set()) { + LyXCursor cur = cursor; + if (cur.pos() == 0 + && !(cur.par()->params().spaceTop() + == VSpace (VSpace::NONE))) { + setParagraph(bv, + cur.par()->params().lineTop(), + cur.par()->params().lineBottom(), + cur.par()->params().pagebreakTop(), + cur.par()->params().pagebreakBottom(), + VSpace(VSpace::NONE), cur.par()->params().spaceBottom(), + cur.par()->params().spacing(), + cur.par()->params().align(), + cur.par()->params().labelWidthString(), 0); + } else { + backspace(bv); + selection.cursor = cur; + } + } else { + update(bv, false); + cutSelection(bv, true); + } + update(bv); + break; + + case LFUN_BREAKPARAGRAPH: + bv->beforeChange(this); + breakParagraph(bv, 0); + update(bv); + selection.cursor = cursor; + bv->switchKeyMap(); + bv->owner()->view_state_changed(); + break; + + case LFUN_BREAKPARAGRAPHKEEPLAYOUT: + bv->beforeChange(this); + breakParagraph(bv, 1); + update(bv); + selection.cursor = cursor; + bv->switchKeyMap(); + bv->owner()->view_state_changed(); + break; + + case LFUN_BREAKPARAGRAPH_SKIP: { + // When at the beginning of a paragraph, remove + // indentation and add a "defskip" at the top. + // Otherwise, do the same as LFUN_BREAKPARAGRAPH. + LyXCursor cur = cursor; + bv->beforeChange(this); + if (cur.pos() == 0) { + if (cur.par()->params().spaceTop() == VSpace(VSpace::NONE)) { + setParagraph(bv, + cur.par()->params().lineTop(), + cur.par()->params().lineBottom(), + cur.par()->params().pagebreakTop(), + cur.par()->params().pagebreakBottom(), + VSpace(VSpace::DEFSKIP), cur.par()->params().spaceBottom(), + cur.par()->params().spacing(), + cur.par()->params().align(), + cur.par()->params().labelWidthString(), 1); + //update(bv); + } + } + else { + breakParagraph(bv, 0); + //update(bv); + } + update(bv); + selection.cursor = cur; + bv->switchKeyMap(); + bv->owner()->view_state_changed(); + break; + } + + case LFUN_PARAGRAPH_SPACING: { + Paragraph * par = cursor.par(); + Spacing::Space cur_spacing = par->params().spacing().getSpace(); + float cur_value = 1.0; + if (cur_spacing == Spacing::Other) + cur_value = par->params().spacing().getValue(); + + istringstream is(cmd.argument.c_str()); + string tmp; + is >> tmp; + Spacing::Space new_spacing = cur_spacing; + float new_value = cur_value; + if (tmp.empty()) { + lyxerr << "Missing argument to `paragraph-spacing'" + << endl; + } else if (tmp == "single") { + new_spacing = Spacing::Single; + } else if (tmp == "onehalf") { + new_spacing = Spacing::Onehalf; + } else if (tmp == "double") { + new_spacing = Spacing::Double; + } else if (tmp == "other") { + new_spacing = Spacing::Other; + float tmpval = 0.0; + is >> tmpval; + lyxerr << "new_value = " << tmpval << endl; + if (tmpval != 0.0) + new_value = tmpval; + } else if (tmp == "default") { + new_spacing = Spacing::Default; + } else { + lyxerr << _("Unknown spacing argument: ") + << cmd.argument << endl; + } + if (cur_spacing != new_spacing || cur_value != new_value) { + par->params().spacing(Spacing(new_spacing, new_value)); + redoParagraph(bv); + update(bv); + } + break; + } + + case LFUN_INSET_TOGGLE: + bv->hideCursor(); + bv->beforeChange(this); + update(bv, false); + toggleInset(bv); + update(bv, false); + bv->switchKeyMap(); + break; case LFUN_PROTECTEDSPACE: if (cursor.par()->layout()->free_spacing) { @@ -370,41 +770,41 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) specialChar(this, bv, InsetSpecialChar::PROTECTED_SEPARATOR); } bv->moveCursorUpdate(false); - return Inset::DISPATCHED; + break; case LFUN_HYPHENATION: specialChar(this, bv, InsetSpecialChar::HYPHENATION); - return Inset::DISPATCHED; + break; case LFUN_LIGATURE_BREAK: specialChar(this, bv, InsetSpecialChar::LIGATURE_BREAK); - return Inset::DISPATCHED; + break; case LFUN_LDOTS: specialChar(this, bv, InsetSpecialChar::LDOTS); - return Inset::DISPATCHED; + break; case LFUN_HFILL: bv->hideCursor(); update(bv, false); insertChar(bv, Paragraph::META_HFILL); update(bv); - return Inset::DISPATCHED; + break; case LFUN_END_OF_SENTENCE: specialChar(this, bv, InsetSpecialChar::END_OF_SENTENCE); - return Inset::DISPATCHED; + break; case LFUN_MENU_SEPARATOR: specialChar(this, bv, InsetSpecialChar::MENU_SEPARATOR); - return Inset::DISPATCHED; + break; case LFUN_MARK_OFF: bv->beforeChange(this); update(bv, false); selection.cursor = cursor; cmd.message(N_("Mark off")); - return Inset::DISPATCHED; + break; case LFUN_MARK_ON: bv->beforeChange(this); @@ -412,7 +812,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv, false); selection.cursor = cursor; cmd.message(N_("Mark on")); - return Inset::DISPATCHED; + break; case LFUN_SETMARK: bv->beforeChange(this); @@ -425,7 +825,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cmd.message(N_("Mark set")); } selection.cursor = cursor; - return Inset::DISPATCHED; + break; case LFUN_UPCASE_WORD: update(bv, false); @@ -433,7 +833,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) if (inset_owner) bv->updateInset(inset_owner, true); update(bv); - return Inset::DISPATCHED; + break; case LFUN_LOWCASE_WORD: update(bv, false); @@ -441,7 +841,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) if (inset_owner) bv->updateInset(inset_owner, true); update(bv); - return Inset::DISPATCHED; + break; case LFUN_CAPITALIZE_WORD: update(bv, false); @@ -449,7 +849,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) if (inset_owner) bv->updateInset(inset_owner, true); update(bv); - return Inset::DISPATCHED; + break; case LFUN_TRANSPOSE_CHARS: update(bv, false); @@ -457,36 +857,66 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) if (inset_owner) bv->updateInset(inset_owner, true); update(bv); - return Inset::DISPATCHED; + break; + + case LFUN_PASTE: + cmd.message(_("Paste")); + bv->hideCursor(); + // clear the selection + bv->toggleSelection(); + clearSelection(); + update(bv, false); + pasteSelection(bv); + clearSelection(); // bug 393 + update(bv, false); + update(bv); + bv->switchKeyMap(); + break; + + case LFUN_CUT: + bv->hideCursor(); + update(bv, false); + cutSelection(bv, true); + update(bv); + cmd.message(_("Cut")); + break; + + case LFUN_COPY: + copySelection(bv); + cmd.message(_("Copy")); + break; case LFUN_BEGINNINGBUFSEL: if (inset_owner) return Inset::UNDISPATCHED; update(bv, false); cursorTop(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_ENDBUFSEL: if (inset_owner) return Inset::UNDISPATCHED; update(bv, false); cursorBottom(bv); - bv->finishChange(true); - return Inset::DISPATCHED; + finishChange(bv, true); + break; case LFUN_GETXY: cmd.message(tostr(cursor.x()) + ' ' + tostr(cursor.y())); - return Inset::DISPATCHED; + break; case LFUN_SETXY: { int x = 0; int y = 0; - if (::sscanf(cmd.argument.c_str(), " %d %d", &x, &y) != 2) + istringstream is(cmd.argument.c_str()); + is >> x >> y; + if (!is) lyxerr << "SETXY: Could not parse coordinates in '" << cmd.argument << std::endl; - setCursorFromCoordinates(bv, x, y); - return Inset::DISPATCHED; + else + setCursorFromCoordinates(bv, x, y); + break; } case LFUN_GETFONT: @@ -496,15 +926,154 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cmd.message("N"); else cmd.message("0"); - return Inset::DISPATCHED; + break; case LFUN_GETLAYOUT: cmd.message(tostr(cursor.par()->layout())); - return Inset::DISPATCHED; + break; + + case LFUN_LAYOUT: { + lyxerr[Debug::INFO] << "LFUN_LAYOUT: (arg) " + << cmd.argument << endl; + + // This is not the good solution to the empty argument + // problem, but it will hopefully suffice for 1.2.0. + // The correct solution would be to augument the + // function list/array with information about what + // functions needs arguments and their type. + if (cmd.argument.empty()) { + cmd.errorMessage(_("LyX function 'layout' needs an argument.")); + break; + } + + // Derive layout number from given argument (string) + // and current buffer's textclass (number) + LyXTextClass const & tclass = bv->buffer()->params.getLyXTextClass(); + bool hasLayout = tclass.hasLayout(cmd.argument); + string layout = cmd.argument; + + // If the entry is obsolete, use the new one instead. + if (hasLayout) { + string const & obs = tclass[layout]->obsoleted_by(); + if (!obs.empty()) + layout = obs; + } + + if (!hasLayout) { + cmd.errorMessage(string(N_("Layout ")) + cmd.argument + + N_(" not known")); + break; + } + + bool change_layout = (current_layout != layout); + if (!change_layout && selection.set() && + selection.start.par() != selection.end.par()) + { + Paragraph * spar = selection.start.par(); + Paragraph * epar = selection.end.par()->next(); + while (spar != epar) { + if (spar->layout()->name() != current_layout) { + change_layout = true; + break; + } + } + } + if (change_layout) { + bv->hideCursor(); + current_layout = layout; + update(bv, false); + setLayout(bv, layout); + bv->owner()->setLayout(layout); + update(bv); + bv->switchKeyMap(); + } + break; + } + + case LFUN_PASTESELECTION: { + if (!bv->buffer()) + break; + bv->hideCursor(); + // this was originally a beforeChange(bv->text), i.e + // the outermost LyXText! + bv->beforeChange(this); + string const clip(bv->workarea().getClipboard()); + if (!clip.empty()) { + if (cmd.argument == "paragraph") + insertStringAsParagraphs(bv, clip); + else + insertStringAsLines(bv, clip); + clearSelection(); + update(bv); + } + break; + } + + case LFUN_GOTOERROR: + gotoInset(bv, Inset::ERROR_CODE, false); + break; + + case LFUN_GOTONOTE: + gotoInset(bv, Inset::NOTE_CODE, false); + break; + + case LFUN_REFERENCE_GOTO: + { + vector tmp; + tmp.push_back(Inset::LABEL_CODE); + tmp.push_back(Inset::REF_CODE); + gotoInset(bv, tmp, true); + break; + } + + case LFUN_QUOTE: { + Paragraph const * par = cursor.par(); + lyx::pos_type pos = cursor.pos(); + char c; + + if (!pos) + c = ' '; + else if (par->isInset(pos - 1) && par->getInset(pos - 1)->isSpace()) + c = ' '; + else + c = par->getChar(pos - 1); + + bv->hideCursor(); + LyXLayout_ptr const & style = par->layout(); + + if (style->pass_thru || + par->getFontSettings(bv->buffer()->params, + pos).language()->lang() == "hebrew" || + (!bv->insertInset(new InsetQuotes(c, bv->buffer()->params)))) + bv->owner()->dispatch(FuncRequest(LFUN_SELFINSERT, "\"")); + break; + } + + case LFUN_DATE_INSERT: { // jdblair: date-insert cmd + time_t now_time_t = time(NULL); + struct tm * now_tm = localtime(&now_time_t); + setlocale(LC_TIME, ""); + string arg; + if (!cmd.argument.empty()) + arg = cmd.argument; + else + arg = lyxrc.date_insert_format; + char datetmp[32]; + int const datetmp_len = + ::strftime(datetmp, 32, arg.c_str(), now_tm); + + for (int i = 0; i < datetmp_len; i++) { + insertChar(bv, datetmp[i]); + update(bv, true); + } + selection.cursor = cursor; + bv->moveCursorUpdate(false); + break; + } case LFUN_SELFINSERT: { if (cmd.argument.empty()) - return Inset::DISPATCHED; + break; // Automatically delete the currently selected // text and replace it with what is being @@ -537,13 +1106,12 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) // update the minibuffer if (old_font != real_current_font) bv->owner()->view_state_changed(); - return Inset::DISPATCHED; + break; } default: return Inset::UNDISPATCHED; } - // shut up compiler - return Inset::UNDISPATCHED; + return Inset::DISPATCHED; }