X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ftext3.C;h=b620c11e71143e39b4b4255989c0dca7623d3dcf;hb=29f01faa17495e3d80c08f234c8f049c7d699ac1;hp=7ed8bedbb1748e21c96b8c53cfbfea617e4f8fbb;hpb=1d4154f33363e61541d39e18fe400864e7b0439a;p=lyx.git diff --git a/src/text3.C b/src/text3.C index 7ed8bedbb1..b620c11e71 100644 --- a/src/text3.C +++ b/src/text3.C @@ -21,15 +21,327 @@ #include "buffer.h" #include "ParagraphParameters.h" #include "gettext.h" +#include "factory.h" #include "intl.h" +#include "box.h" +#include "language.h" #include "support/lstrings.h" #include "frontends/LyXView.h" -#include "frontends/WorkArea.h" +#include "frontends/screen.h" +#include "frontends/Dialogs.h" #include "insets/insetspecialchar.h" #include "insets/insettext.h" +#include "insets/insetbib.h" +#include "insets/insetquotes.h" +#include "insets/insetcommand.h" +#include "undo_funcs.h" +#include +#include + +using std::endl; extern string current_layout; +extern int bibitemMaxWidth(BufferView *, LyXFont const &); + +// the selection possible is needed, that only motion events are +// used, where the bottom press event was on the drawing area too +bool selection_possible = false; + + +namespace { + + void moveCursorUpdate(BufferView * bv, bool selecting) + { + LyXText * lt = bv->getLyXText(); + + if (selecting || lt->selection.mark()) { + lt->setSelection(bv); + if (lt->bv_owner) + bv->toggleToggle(); + else + bv->updateInset(lt->inset_owner, false); + } + if (lt->bv_owner) { + //if (fitcur) + // bv->update(lt, BufferView::SELECT|BufferView::FITCUR); + //else + bv->update(lt, BufferView::SELECT|BufferView::FITCUR); + bv->showCursor(); + } else if (bv->text->status() != LyXText::UNCHANGED) { + bv->theLockingInset()->hideInsetCursor(bv); + bv->update(bv->text, BufferView::SELECT|BufferView::FITCUR); + bv->showCursor(); + } + + if (!lt->selection.set()) + bv->haveSelection(false); + + bv->switchKeyMap(); + } + + + void finishChange(BufferView * bv, bool selecting = false) + { + finishUndo(); + moveCursorUpdate(bv, selecting); + bv->owner()->view_state_changed(); + } + + // check if the given co-ordinates are inside an inset at the + // given cursor, if one exists. If so, the inset is returned, + // and the co-ordinates are made relative. Otherwise, 0 is returned. + Inset * checkInset(BufferView * bv, LyXText const & text, + LyXCursor const & cur, int & x, int & y) + { + lyx::pos_type const pos = cur.pos(); + Paragraph /*const*/ & par = *cur.par(); + + if (pos >= par.size() || !par.isInset(pos)) + return 0; + + Inset /*const*/ * inset = par.getInset(pos); + + if (!isEditableInset(inset)) + return 0; + + // get inset dimensions + lyx::Assert(par.getInset(pos)); + + LyXFont const & font = text.getFont(bv->buffer(), &par, pos); + + int const width = inset->width(bv, font); + int const inset_x = font.isVisibleRightToLeft() + ? (cur.ix() - width) : cur.ix(); + + Box b( + inset_x + inset->scroll(), + inset_x + width, + cur.iy() - inset->ascent(bv, font), + cur.iy() + inset->descent(bv, font) + ); + + if (!b.contained(x, y)) { + lyxerr[Debug::GUI] << "Missed inset at x,y " << x << "," << y + << " box " << b << endl; + return 0; + } + + text.setCursor(bv, &par, pos, true); + + x -= b.x1; + // The origin of an inset is on the baseline + y -= text.cursor.iy(); + + return inset; + } + +} // anon namespace + + +Inset * LyXText::checkInsetHit(BufferView * bv, int & x, int & y) const +{ + int y_tmp = y + first_y; + + LyXCursor cur; + setCursorFromCoordinates(bv, cur, x, y_tmp); + + Inset * inset = checkInset(bv, *this, cur, x, y_tmp); + if (inset) { + y = y_tmp; + return inset; + } + + // look at previous position + if (cur.pos() == 0) + return 0; + + // move back one + setCursor(bv, cur, cur.par(), cur.pos() - 1, true); + + inset = checkInset(bv, *this, cur, x, y_tmp); + if (inset) + y = y_tmp; + return inset; +} + + +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->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->workHeight(); + } else { + if (inset_owner) { + new_y = bv->text->cursor.iy() + + bv->theLockingInset()->insetInInsetY() + y + + cursor.row()->height() + - bv->workHeight() + 1; + } else { + new_y = cursor.y() + - cursor.row()->baseline() + + cursor.row()->height() + - bv->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->workHeight())) { + bv->screen().draw(bv->text, bv, + bv->text->first_y + bv->workHeight()); + bv->updateScrollbar(); + } + return; + } + + int y = first_y + bv->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); + // + bv->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->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->workHeight())) { + cursorDown(bv, true); + } + } + bv->updateScrollbar(); +} void LyXText::update(BufferView * bv, bool changed) @@ -56,6 +368,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) { @@ -86,7 +401,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv, false); deleteWordForward(bv); update(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_DELETE_WORD_BACKWARD: @@ -94,7 +409,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv, false); deleteWordBackward(bv); update(bv, true); - bv->finishChange(); + finishChange(bv); break; case LFUN_DELETE_LINE_FORWARD: @@ -102,7 +417,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv, false); deleteLineForward(bv); update(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_SHIFT_TAB: @@ -111,10 +426,10 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); update(bv, false); cursorTab(bv); - bv->finishChange(); + finishChange(bv); break; - case LFUN_WORDRIGHT: + case LFUN_WORDRIGHT: if (!selection.mark()) bv->beforeChange(this); update(bv, false); @@ -122,7 +437,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeftOneWord(bv); else cursorRightOneWord(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_WORDLEFT: @@ -133,7 +448,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorRightOneWord(bv); else cursorLeftOneWord(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_BEGINNINGBUF: @@ -141,7 +456,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); update(bv, false); cursorTop(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_ENDBUF: @@ -149,7 +464,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); update(bv, false); cursorBottom(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_RIGHTSEL: @@ -158,7 +473,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeft(bv); else cursorRight(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_LEFTSEL: @@ -167,55 +482,55 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorRight(bv); else cursorLeft(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_UPSEL: update(bv, false); cursorUp(bv, true); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_DOWNSEL: update(bv, false); cursorDown(bv, true); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_UP_PARAGRAPHSEL: update(bv, false); cursorUpParagraph(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_DOWN_PARAGRAPHSEL: update(bv, false); cursorDownParagraph(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_PRIORSEL: update(bv, false); - bv->cursorPrevious(this); - bv->finishChange(true); + cursorPrevious(bv); + finishChange(bv, true); break; case LFUN_NEXTSEL: update(bv, false); - bv->cursorNext(this); - bv->finishChange(); + cursorNext(bv); + finishChange(bv, true); break; case LFUN_HOMESEL: update(bv, false); cursorHome(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_ENDSEL: update(bv, false); cursorEnd(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_WORDRIGHTSEL: @@ -224,7 +539,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeftOneWord(bv); else cursorRightOneWord(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_WORDLEFTSEL: @@ -233,7 +548,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorRightOneWord(bv); else cursorLeftOneWord(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_RIGHT: { @@ -253,7 +568,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) } if (!is_rtl) cursorRight(bv, false); - bv->finishChange(false); + finishChange(bv); break; } @@ -278,7 +593,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) } if (is_rtl) cursorRight(bv, false); - bv->finishChange(false); + finishChange(bv); break; } @@ -287,7 +602,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorUp(bv); - bv->finishChange(false); + finishChange(bv); break; case LFUN_DOWN: @@ -295,7 +610,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorDown(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_UP_PARAGRAPH: @@ -303,7 +618,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorUpParagraph(bv); - bv->finishChange(); + finishChange(bv); break; case LFUN_DOWN_PARAGRAPH: @@ -311,18 +626,18 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); cursorDownParagraph(bv); - bv->finishChange(false); + 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); + // moveCursorUpdate(bv, false, false); // owner_->view_state_changed(); break; @@ -330,8 +645,8 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) if (!selection.mark()) bv->beforeChange(this); bv->update(this, BufferView::UPDATE); - bv->cursorNext(this); - bv->finishChange(false); + cursorNext(bv); + finishChange(bv, false); break; case LFUN_HOME: @@ -339,7 +654,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); update(bv); cursorHome(bv); - bv->finishChange(false); + finishChange(bv, false); break; case LFUN_END: @@ -347,7 +662,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) bv->beforeChange(this); update(bv); cursorEnd(bv); - bv->finishChange(false); + finishChange(bv, false); break; case LFUN_BREAKLINE: @@ -355,7 +670,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) insertChar(bv, Paragraph::META_NEWLINE); update(bv, true); setCursor(bv, cursor.par(), cursor.pos()); - bv->moveCursorUpdate(false); + moveCursorUpdate(bv, false); break; case LFUN_DELETE: @@ -367,9 +682,11 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) // just comment out the line below... bv->showCursor(); } else { - bv->cut(false); + update(bv, false); + cutSelection(bv, true); + update(bv); } - bv->moveCursorUpdate(false); + moveCursorUpdate(bv, false); bv->owner()->view_state_changed(); bv->switchKeyMap(); break; @@ -400,15 +717,16 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cursorLeft(bv); Delete(bv); selection.cursor = cursor; - update(bv); } } else { Delete(bv); selection.cursor = cursor; - update(bv); } - } else - bv->cut(false); + } else { + update(bv, false); + cutSelection(bv, true); + } + update(bv); break; @@ -422,8 +740,11 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) // just comment out the line below... bv->showCursor(); } - } else - bv->cut(false); + } else { + update(bv, false); + cutSelection(bv, true); + update(bv); + } bv->owner()->view_state_changed(); bv->switchKeyMap(); break; @@ -444,14 +765,15 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cur.par()->params().spacing(), cur.par()->params().align(), cur.par()->params().labelWidthString(), 0); - update(bv); } else { backspace(bv); selection.cursor = cur; - update(bv); } - } else - bv->cut(false); + } else { + update(bv, false); + cutSelection(bv, true); + } + update(bv); break; case LFUN_BREAKPARAGRAPH: @@ -561,7 +883,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) } else { specialChar(this, bv, InsetSpecialChar::PROTECTED_SEPARATOR); } - bv->moveCursorUpdate(false); + moveCursorUpdate(bv, false); break; case LFUN_HYPHENATION: @@ -651,12 +973,39 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv); 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); + finishChange(bv, true); break; case LFUN_ENDBUFSEL: @@ -664,7 +1013,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) return Inset::UNDISPATCHED; update(bv, false); cursorBottom(bv); - bv->finishChange(true); + finishChange(bv, true); break; case LFUN_GETXY: @@ -674,10 +1023,13 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) 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); + else + setCursorFromCoordinates(bv, x, y); break; } @@ -759,11 +1111,11 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) // this was originally a beforeChange(bv->text), i.e // the outermost LyXText! bv->beforeChange(this); - string const clip(bv->workarea().getClipboard()); + string const clip = bv->getClipboard(); if (!clip.empty()) { if (cmd.argument == "paragraph") insertStringAsParagraphs(bv, clip); - else + else insertStringAsLines(bv, clip); clearSelection(); update(bv); @@ -771,6 +1123,392 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) 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: { + 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; + moveCursorUpdate(bv, false); + break; + } + + case LFUN_MOUSE_TRIPLE: + if (!bv->buffer()) + break; + if (bv_owner && bv->theLockingInset()) + break; + if (cmd.button() == mouse_button::button1) { + if (bv_owner) { + bv->screen().hideCursor(); + bv->screen().toggleSelection(this, bv); + } + cursorHome(bv); + selection.cursor = cursor; + cursorEnd(bv); + setSelection(bv); + if (bv_owner) + bv->screen().toggleSelection(this, bv, false); + update(bv, false); + bv->haveSelection(selection.set()); + } + break; + + case LFUN_MOUSE_DOUBLE: + if (!bv->buffer()) + break; + if (bv_owner && bv->theLockingInset()) + break; + if (cmd.button() == mouse_button::button1) { + if (bv_owner) { + bv->screen().hideCursor(); + bv->screen().toggleSelection(this, bv); + selectWord(bv, LyXText::WHOLE_WORD_STRICT); + bv->screen().toggleSelection(this, bv, false); + } else { + selectWord(bv, LyXText::WHOLE_WORD_STRICT); + } + update(bv, false); + bv->haveSelection(selection.set()); + } + break; + + case LFUN_MOUSE_MOTION: + { + // Only use motion with button 1 + //if (ev.button() != mouse_button::button1) + // return false; + + if (!bv->buffer()) + break; + + // Check for inset locking + if (bv->theLockingInset()) { + Inset * tli = bv->theLockingInset(); + LyXCursor cursor = bv->text->cursor; + LyXFont font = bv->text->getFont(bv->buffer(), + cursor.par(), cursor.pos()); + int width = tli->width(bv, font); + int inset_x = font.isVisibleRightToLeft() + ? cursor.ix() - width : cursor.ix(); + int start_x = inset_x + tli->scroll(); + FuncRequest cmd1 = cmd; + cmd1.x = cmd.x - start_x; + cmd1.y = cmd.y - cursor.iy() + bv->text->first_y; + tli->localDispatch(cmd1); + break; + } + + // The test for not selection possible is needed, that only motion + // events are used, where the bottom press event was on + // the drawing area too + if (!selection_possible) { + lyxerr[Debug::ACTION] + << "BufferView::Pimpl::Dispatch: no selection possible\n"; + break; + } + + bv->screen().hideCursor(); + + Row * cursorrow = bv->text->cursor.row(); + bv->text->setCursorFromCoordinates(bv, cmd.x, cmd.y + bv->text->first_y); + #if 0 + // sorry for this but I have a strange error that the y value jumps at + // a certain point. This seems like an error in my xforms library or + // in some other local environment, but I would like to leave this here + // for the moment until I can remove this (Jug 20020418) + if (y_before < bv->text->cursor.y()) + lyxerr << y_before << ":" << bv->text->cursor.y() << endl; + #endif + // This is to allow jumping over large insets + if (cursorrow == bv->text->cursor.row()) { + if (cmd.y >= int(bv->workHeight())) + bv->text->cursorDown(bv, false); + else if (cmd.y < 0) + bv->text->cursorUp(bv, false); + } + + // Maybe an empty line was deleted + if (!bv->text->selection.set()) + bv->update(bv->text, BufferView::UPDATE); + bv->text->setSelection(bv); + bv->screen().toggleToggle(bv->text, bv); + bv->fitCursor(); + bv->showCursor(); + break; + } + + // Single-click on work area + case LFUN_MOUSE_PRESS: + { + if (!bv->buffer()) + break; + + // ok ok, this is a hack (for xforms) + // We shouldn't go further down as we really should only do the + // scrolling and be done with this. Otherwise we may open some + // dialogs (Jug 20020424). + if (cmd.button() == mouse_button::button4) { + bv->scroll(-lyxrc.wheel_jump); + break; + } + if (cmd.button() == mouse_button::button5) { + bv->scroll(lyxrc.wheel_jump); + break; + } + + int x = cmd.x; + int y = cmd.y; + Inset * inset_hit = bv->text->checkInsetHit(bv, x, y); + + // Middle button press pastes if we have a selection + // We do this here as if the selection was inside an inset + // it could get cleared on the unlocking of the inset so + // we have to check this first + bool paste_internally = false; + if (cmd.button() == mouse_button::button2 && selection.set()) { + bv->owner()->dispatch(FuncRequest(LFUN_COPY)); + paste_internally = true; + } + + int const screen_first = bv->text->first_y; + + if (bv->theLockingInset()) { + // We are in inset locking mode + + // Check whether the inset was hit. If not reset mode, + // otherwise give the event to the inset + if (inset_hit == bv->theLockingInset()) { + FuncRequest cmd1(bv, LFUN_MOUSE_PRESS, x, y, cmd.button()); + bv->theLockingInset()->localDispatch(cmd1); + break; + } + bv->unlockInset(bv->theLockingInset()); + } + + if (!inset_hit) + selection_possible = true; + bv->screen().hideCursor(); + + // Clear the selection + bv->screen().toggleSelection(bv->text, bv); + bv->text->clearSelection(); + bv->text->fullRebreak(bv); + bv->update(); + bv->updateScrollbar(); + + // Single left click in math inset? + if (isHighlyEditableInset(inset_hit)) { + // Highly editable inset, like math + UpdatableInset * inset = static_cast(inset_hit); + selection_possible = false; + bv->owner()->updateLayoutChoice(); + bv->owner()->message(inset->editMessage()); + //inset->edit(bv, x, y, cmd.button()); + // We just have to lock the inset before calling a PressEvent on it! + // we don't need the edit() call here! (Jug20020329) + if (!bv->lockInset(inset)) + lyxerr[Debug::INSETS] << "Cannot lock inset" << endl; + FuncRequest cmd1(bv, LFUN_MOUSE_PRESS, x, y, cmd.button()); + inset->localDispatch(cmd1); + break; + } + // I'm not sure we should continue here if we hit an inset (Jug20020403) + + // Right click on a footnote flag opens float menu + if (cmd.button() == mouse_button::button3) { + selection_possible = false; + break; + } + + if (!inset_hit) // otherwise it was already set in checkInsetHit(...) + bv->text->setCursorFromCoordinates(bv, x, y + screen_first); + finishUndo(); + bv->text->selection.cursor = bv->text->cursor; + bv->text->cursor.x_fix(bv->text->cursor.x()); + + bv->owner()->updateLayoutChoice(); + if (bv->fitCursor()) + selection_possible = false; + + // 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 (paste_internally) + bv->owner()->dispatch(FuncRequest(LFUN_PASTE)); + else + bv->owner()->dispatch(FuncRequest(LFUN_PASTESELECTION, "paragraph")); + selection_possible = false; + } + break; + } + + case LFUN_MOUSE_RELEASE: + { + // do nothing if we used the mouse wheel + if (!bv->buffer()) + break; + + if (cmd.button() == mouse_button::button4 + || cmd.button() == mouse_button::button5) + break; + + // If we hit an inset, we have the inset coordinates in these + // and inset_hit points to the inset. If we do not hit an + // inset, inset_hit is 0, and inset_x == x, inset_y == y. + int x = cmd.x; + int y = cmd.y; + Inset * inset_hit = bv->text->checkInsetHit(bv, x, y); + + if (bv->theLockingInset()) { + // We are in inset locking mode. + + // LyX does a kind of work-area grabbing for insets. + // Only a ButtonPress FuncRequest outside the inset will + // force a insetUnlock. + FuncRequest cmd1(bv, LFUN_MOUSE_RELEASE, x, y, cmd.button()); + bv->theLockingInset()->localDispatch(cmd1); + break; + } + + selection_possible = false; + + if (cmd.button() == mouse_button::button2) + break; + + // finish selection + if (cmd.button() == mouse_button::button1) + bv->haveSelection(selection.set()); + + bv->switchKeyMap(); + bv->owner()->view_state_changed(); + bv->owner()->updateMenubar(); + bv->owner()->updateToolbar(); + + // Did we hit an editable inset? + if (inset_hit) { + selection_possible = false; + + // if we reach this point with a selection, it + // must mean we are currently selecting. + // But we don't want to open the inset + // because that is annoying for the user. + // So just pretend we didn't hit it. + // this is OK because a "kosher" ButtonRelease + // will follow a ButtonPress that clears + // the selection. + // Note this also fixes selection drawing + // problems if we end up opening an inset + if (selection.set()) + break; + + // CHECK fix this proper in 0.13 + // well, maybe 13.0 !!!!!!!!! + + // Following a ref shouldn't issue + // a push on the undo-stack + // anylonger, now that we have + // keybindings for following + // references and returning from + // references. IMHO though, it + // should be the inset's own business + // to push or not push on the undo + // stack. They don't *have* to + // alter the document... + // (Joacim) + // ...or maybe the SetCursorParUndo() + // below isn't necessary at all anylonger? + if (inset_hit->lyxCode() == Inset::REF_CODE) + setCursorParUndo(bv); + + bv->owner()->message(inset_hit->editMessage()); + + if (isHighlyEditableInset(inset_hit)) { + // Highly editable inset, like math + UpdatableInset * inset = (UpdatableInset *) inset_hit; + FuncRequest cmd1(bv, LFUN_MOUSE_RELEASE, x, y, cmd.button()); + inset->localDispatch(cmd1); + } else { + FuncRequest cmd1(bv, LFUN_MOUSE_RELEASE, x, y, cmd.button()); + inset_hit->localDispatch(cmd1); + // IMO this is a grosshack! Inset's should be changed so that + // they call the actions they have to do with the insetButtonRel. + // function and not in the edit(). This should be changed + // (Jug 20020329) +#ifdef WITH_WARNINGS +#warning Please remove donot call inset->edit() here (Jug 20020812) +#endif + inset_hit->edit(bv, x, y, cmd.button()); + } + break; + } + + // Maybe we want to edit a bibitem ale970302 + if (bv->text->cursor.par()->bibkey) { + bool const is_rtl = + bv->text->cursor.par()->isRightToLeftPar(bv->buffer()->params); + int const width = + bibitemMaxWidth(bv, bv->buffer()->params.getLyXTextClass().defaultfont()); + if ((is_rtl && x > bv->text->workWidth(bv)-20-width) || + (!is_rtl && x < 20 + width)) { + bv->text->cursor.par()->bibkey->edit(bv, 0, 0, mouse_button::none); + } + } + break; + } + case LFUN_SELFINSERT: { if (cmd.argument.empty()) break; @@ -786,7 +1524,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) cutSelection(bv, false, false); update(bv); } - bv->workarea().haveSelection(false); + bv->haveSelection(false); } bv->beforeChange(this); @@ -800,7 +1538,7 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) update(bv); selection.cursor = cursor; - bv->moveCursorUpdate(false); + moveCursorUpdate(bv, false); // real_current_font.number can change so we need to // update the minibuffer @@ -809,6 +1547,59 @@ Inset::RESULT LyXText::dispatch(FuncRequest const & cmd) break; } + case LFUN_HTMLURL: { + InsetCommandParams p("htmlurl"); + bv->owner()->getDialogs().createUrl(p.getAsString()); + break; + } + + case LFUN_URL: { + InsetCommandParams p("url"); + bv->owner()->getDialogs().createUrl(p.getAsString()); + break; + } + + +#if 0 + case LFUN_INSET_LIST: + case LFUN_INSET_THEOREM: +#endif + case LFUN_INSERT_NOTE: + case LFUN_INSERT_URL: + case LFUN_INSET_CAPTION: + case LFUN_INSET_ERT: + case LFUN_INSET_EXTERNAL: + case LFUN_INSET_FLOAT: + case LFUN_INSET_FOOTNOTE: + case LFUN_INSET_MARGINAL: + case LFUN_INSET_MINIPAGE: + case LFUN_INSET_OPTARG: + case LFUN_INSET_WIDE_FLOAT: + case LFUN_TABULAR_INSERT: + case LFUN_INDEX_INSERT: + case LFUN_INDEX_PRINT: + case LFUN_PARENTINSERT: + case LFUN_TOC_INSERT: + { + Inset * inset = createInset(cmd); + if (inset) { + bool gotsel = false; + if (selection.set()) { + cutSelection(bv, true, false); + gotsel = true; + } + if (bv->insertInset(inset)) { + inset->edit(bv); + if (gotsel) + bv->owner()->dispatch(FuncRequest(LFUN_PASTESELECTION)); + } + else + delete inset; + } + break; + } + + default: return Inset::UNDISPATCHED; }