X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBufferView_pimpl.C;h=e0a6b0157c7ba363054001552e6be7770a18d58f;hb=1e394731004491d04abe436112b5a89521bbd19a;hp=f8bcd15520cb494e75532812aeece4514e4fec07;hpb=54e7ddb5d9a348ae9cfc60f399e9c0c2658ab4c5;p=lyx.git diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index f8bcd15520..e0a6b0157c 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -1,42 +1,39 @@ #include -#include -#include -#include -#include - #ifdef __GNUG__ #pragma implementation #endif #include "BufferView_pimpl.h" -#include "WorkArea.h" -#include "lyxscreen.h" +#include "frontends/WorkArea.h" +#include "frontends/screen.h" #include "lyxtext.h" #include "lyxrow.h" -#include "LyXView.h" +#include "paragraph.h" +#include "frontends/LyXView.h" #include "commandtags.h" #include "lyxfunc.h" #include "debug.h" -#include "font.h" #include "bufferview_funcs.h" #include "TextCache.h" #include "bufferlist.h" -#include "lyx_gui_misc.h" #include "lyxrc.h" #include "intl.h" -#include "support/LAssert.h" -#include "support/lstrings.h" -#include "frontends/Dialogs.h" -#include "insets/insetbib.h" -#include "insets/insettext.h" -/// added for Dispatch functions +// added for Dispatch functions #include "lyx_cb.h" -#include "frontends/FileDialog.h" #include "lyx_main.h" #include "FloatList.h" -#include "support/filetools.h" -#include "support/lyxfunctional.h" +#include "gettext.h" +#include "ParagraphParameters.h" +#include "undo_funcs.h" +#include "lyxtextclasslist.h" + +#include "frontends/Dialogs.h" +#include "frontends/Alert.h" +#include "frontends/FileDialog.h" + +#include "insets/insetbib.h" +#include "insets/insettext.h" #include "insets/inseturl.h" #include "insets/insetlatexaccent.h" #include "insets/insettoc.h" @@ -61,12 +58,23 @@ #include "insets/insetcaption.h" #include "insets/insetfloatlist.h" #include "insets/insetspecialchar.h" -#include "gettext.h" -#include "ParagraphParameters.h" -#include "undo_funcs.h" + #include "mathed/formulabase.h" -extern LyXTextClass::size_type current_layout; +#include "support/LAssert.h" +#include "support/lstrings.h" +#include "support/filetools.h" +#include "support/lyxfunctional.h" + +#include + +#include +#include +#include +#include + + +extern string current_layout; using std::vector; using std::find_if; @@ -75,16 +83,17 @@ using std::pair; using std::endl; using std::make_pair; using std::min; -using SigC::slot; -/* the selection possible is needed, that only motion events are +using lyx::pos_type; +using lyx::textclass_type; + +/* 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; extern BufferList bufferlist; extern char ascii_type; -extern void sigchldchecker(pid_t pid, int * status); extern int bibitemMaxWidth(BufferView *, LyXFont const &); @@ -103,7 +112,7 @@ void SetXtermCursor(Window win) { static Cursor cursor; static bool cursor_undefined = true; - if (cursor_undefined){ + if (cursor_undefined) { cursor = XCreateFontCursor(fl_get_display(), XC_xterm); XFlush(fl_get_display()); cursor_undefined = false; @@ -123,36 +132,38 @@ BufferView::Pimpl::Pimpl(BufferView * b, LyXView * o, inset_slept(false) { // Setup the signals - workarea_.scrollCB.connect(slot(this, &BufferView::Pimpl::scrollCB)); + workarea_.scrollCB.connect(boost::bind(&BufferView::Pimpl::scrollCB, this, _1)); workarea_.workAreaExpose - .connect(slot(this, &BufferView::Pimpl::workAreaExpose)); + .connect(boost::bind(&BufferView::Pimpl::workAreaExpose, this)); workarea_.workAreaEnter - .connect(slot(this, &BufferView::Pimpl::enterView)); + .connect(boost::bind(&BufferView::Pimpl::enterView, this)); workarea_.workAreaLeave - .connect(slot(this, &BufferView::Pimpl::leaveView)); + .connect(boost::bind(&BufferView::Pimpl::leaveView, this)); workarea_.workAreaButtonPress - .connect(slot(this, &BufferView::Pimpl::workAreaButtonPress)); + .connect(boost::bind(&BufferView::Pimpl::workAreaButtonPress, this, _1, _2, _3)); workarea_.workAreaButtonRelease - .connect(slot(this, - &BufferView::Pimpl::workAreaButtonRelease)); + .connect(boost::bind(&BufferView::Pimpl::workAreaButtonRelease, this, _1, _2, _3)); workarea_.workAreaMotionNotify - .connect(slot(this, &BufferView::Pimpl::workAreaMotionNotify)); + .connect(boost::bind(&BufferView::Pimpl::workAreaMotionNotify, this, _1, _2, _3)); workarea_.workAreaDoubleClick - .connect(slot(this, &BufferView::Pimpl::doubleClick)); + .connect(boost::bind(&BufferView::Pimpl::doubleClick, this, _1, _2, _3)); workarea_.workAreaTripleClick - .connect(slot(this, &BufferView::Pimpl::tripleClick)); + .connect(boost::bind(&BufferView::Pimpl::tripleClick, this, _1, _2, _3)); workarea_.workAreaKeyPress - .connect(slot(this, &BufferView::Pimpl::workAreaKeyPress)); - - cursor_timeout.timeout.connect(slot(this, - &BufferView::Pimpl::cursorToggle)); + .connect(boost::bind(&BufferView::Pimpl::workAreaKeyPress, this, _1, _2)); + workarea_.selectionRequested + .connect(boost::bind(&BufferView::Pimpl::selectionRequested, this)); + workarea_.selectionLost + .connect(boost::bind(&BufferView::Pimpl::selectionLost, this)); + + cursor_timeout.timeout.connect(boost::bind(&BufferView::Pimpl::cursorToggle, this)); cursor_timeout.start(); workarea_.setFocus(); saved_positions.resize(saved_positions_num); } -Painter & BufferView::Pimpl::painter() +Painter & BufferView::Pimpl::painter() { return workarea_.getPainter(); } @@ -163,7 +174,9 @@ void BufferView::Pimpl::buffer(Buffer * b) lyxerr[Debug::INFO] << "Setting buffer in BufferView (" << b << ")" << endl; if (buffer_) { +#if 0 insetSleep(); +#endif buffer_->delUser(bv_); // Put the old text into the TextCache, but @@ -173,7 +186,7 @@ void BufferView::Pimpl::buffer(Buffer * b) textcache.add(buffer_, workarea_.workWidth(), bv_->text); if (lyxerr.debugging()) textcache.show(lyxerr, "BufferView::buffer"); - + bv_->text = 0; } @@ -181,7 +194,7 @@ void BufferView::Pimpl::buffer(Buffer * b) buffer_ = b; if (bufferlist.getState() == BufferList::CLOSING) return; - + // Nuke old image // screen is always deleted when the buffer is changed. screen_.reset(0); @@ -201,7 +214,7 @@ void BufferView::Pimpl::buffer(Buffer * b) updateScreen(); updateScrollbar(); } - bv_->text->first = screen_->topCursorVisible(bv_->text); + bv_->text->first_y = screen_->topCursorVisible(bv_->text); owner_->updateMenubar(); owner_->updateToolbar(); // Similarly, buffer-dependent dialogs should be updated or @@ -209,7 +222,9 @@ void BufferView::Pimpl::buffer(Buffer * b) // require bv_->text. owner_->getDialogs()->updateBufferDependent(true); redraw(); +#if 0 insetWakeup(); +#endif } else { lyxerr[Debug::INFO] << " No Buffer!" << endl; owner_->updateMenubar(); @@ -287,15 +302,15 @@ void BufferView::Pimpl::redoCurrentBuffer() int BufferView::Pimpl::resizeCurrentBuffer() { lyxerr[Debug::INFO] << "resizeCurrentBuffer" << endl; - + Paragraph * par = 0; Paragraph * selstartpar = 0; Paragraph * selendpar = 0; UpdatableInset * the_locking_inset = 0; - - Paragraph::size_type pos = 0; - Paragraph::size_type selstartpos = 0; - Paragraph::size_type selendpos = 0; + + pos_type pos = 0; + pos_type selstartpos = 0; + pos_type selendpos = 0; bool selection = false; bool mark_set = false; @@ -313,6 +328,9 @@ int BufferView::Pimpl::resizeCurrentBuffer() selection = bv_->text->selection.set(); mark_set = bv_->text->selection.mark(); the_locking_inset = bv_->theLockingInset(); + buffer_->resizeInsets(bv_); + // I don't think the delete and new are necessary here we just could + // call only init! (Jug 20020419) delete bv_->text; bv_->text = new LyXText(bv_); bv_->text->init(bv_); @@ -332,14 +350,16 @@ int BufferView::Pimpl::resizeCurrentBuffer() } else { bv_->text = new LyXText(bv_); bv_->text->init(bv_); + //buffer_->resizeInsets(bv_); } } + updateScreen(); if (par) { bv_->text->selection.set(true); - /* at this point just to avoid the Delete-Empty-Paragraph - * Mechanism when setting the cursor */ + // At this point just to avoid the Delete-Empty-Paragraph- + // Mechanism when setting the cursor. bv_->text->selection.mark(mark_set); if (selection) { bv_->text->setCursor(bv_, selstartpar, selstartpos); @@ -355,8 +375,9 @@ int BufferView::Pimpl::resizeCurrentBuffer() // remake the inset locking bv_->theLockingInset(the_locking_inset); } - bv_->text->first = screen_->topCursorVisible(bv_->text); - buffer_->resizeInsets(bv_); + + bv_->text->first_y = screen_->topCursorVisible(bv_->text); + // this will scroll the screen such that the cursor becomes visible updateScrollbar(); redraw(); @@ -364,12 +385,9 @@ int BufferView::Pimpl::resizeCurrentBuffer() setState(); owner_->allowInput(); - /// clear the "Formatting Document" message + /// clear the "Formatting Document" message owner_->message(""); - - /// get rid of the splash screen if it's not gone already - owner_->getDialogs()->destroySplash(); - + return 0; } @@ -383,50 +401,52 @@ void BufferView::Pimpl::updateScreen() void BufferView::Pimpl::updateScrollbar() { - /* If the text is smaller than the working area, the scrollbar - * maximum must be the working area height. No scrolling will - * be possible */ if (!bv_->text) { + lyxerr[Debug::GUI] << "no text in updateScrollbar" << endl; workarea_.setScrollbar(0, 1.0); return; } long const text_height = bv_->text->height; + long const work_height = workarea_.height(); double const lineh = bv_->text->defaultHeight(); double const slider_size = (text_height == 0) ? 1.0 : 1.0 / double(text_height); - static long old_text_height = 0; - static double old_lineh = 0; - static double old_slider_size = 0; + lyxerr[Debug::GUI] << "text_height now " << text_height << endl; + lyxerr[Debug::GUI] << "work_height " << work_height << endl; - if (text_height != old_text_height) { - workarea_.setScrollbarBounds(0, text_height - workarea_.height()); - old_text_height = text_height; - } - if (lineh != old_lineh) { - workarea_.setScrollbarIncrements(lineh); - old_lineh = lineh; - } - if (current_scrollbar_value != bv_->text->first - || slider_size != old_slider_size) { - current_scrollbar_value = bv_->text->first; - workarea_.setScrollbar(current_scrollbar_value, slider_size); - old_slider_size = slider_size; + /* If the text is smaller than the working area, the scrollbar + * maximum must be the working area height. No scrolling will + * be possible */ + if (text_height <= work_height) { + lyxerr[Debug::GUI] << "doc smaller than workarea !" << endl; + workarea_.setScrollbarBounds(0.0, 0.0); + current_scrollbar_value = bv_->text->first_y; + workarea_.setScrollbar(current_scrollbar_value, 1.0); + return; } + + workarea_.setScrollbarBounds(0.0, text_height - work_height); + workarea_.setScrollbarIncrements(lineh); + current_scrollbar_value = bv_->text->first_y; + workarea_.setScrollbar(current_scrollbar_value, slider_size); } // Callback for scrollbar slider void BufferView::Pimpl::scrollCB(double value) { + lyxerr[Debug::GUI] << "scrollCB of " << value << endl; + if (!buffer_) return; current_scrollbar_value = long(value); + if (current_scrollbar_value < 0) current_scrollbar_value = 0; - + if (!screen_.get()) return; @@ -436,12 +456,12 @@ void BufferView::Pimpl::scrollCB(double value) waitForX(); return; } - + LyXText * vbt = bv_->text; - + int const height = vbt->defaultHeight(); - int const first = static_cast((bv_->text->first + height)); - int const last = static_cast((bv_->text->first + workarea_.height() - height)); + int const first = static_cast((bv_->text->first_y + height)); + int const last = static_cast((bv_->text->first_y + workarea_.height() - height)); if (vbt->cursor.y() < first) vbt->setCursorFromCoordinates(bv_, 0, first); @@ -454,72 +474,82 @@ void BufferView::Pimpl::scrollCB(double value) int BufferView::Pimpl::scrollUp(long time) { - if (!buffer_) return 0; - if (!screen_.get()) return 0; - + if (!buffer_ || !screen_.get()) + return 0; + double value = workarea_.getScrollbarValue(); - - if (value == 0) return 0; + if (value == 0) + return 0; + +#if 1 float add_value = (bv_->text->defaultHeight() + float(time) * float(time) * 0.125); - + if (add_value > workarea_.height()) add_value = float(workarea_.height() - bv_->text->defaultHeight()); - +#else + float add_value = float(workarea_.height()) * float(time) / 100; +#endif + value -= add_value; if (value < 0) value = 0; - + workarea_.setScrollbarValue(value); - - scrollCB(value); + + scrollCB(value); return 0; } int BufferView::Pimpl::scrollDown(long time) { - if (!buffer_) return 0; - if (!screen_.get()) return 0; - + if (!buffer_ || !screen_.get()) + return 0; + double value = workarea_.getScrollbarValue(); pair p = workarea_.getScrollbarBounds(); double const max = p.second; - - if (value == max) return 0; + if (value == max) + return 0; + +#if 1 float add_value = (bv_->text->defaultHeight() + float(time) * float(time) * 0.125); - + if (add_value > workarea_.height()) add_value = float(workarea_.height() - bv_->text->defaultHeight()); - +#else + float add_value = float(workarea_.height()) * float(time) / 100; +#endif + value += add_value; - + if (value > max) value = max; workarea_.setScrollbarValue(value); - - scrollCB(value); + + scrollCB(value); return 0; } -void BufferView::Pimpl::workAreaKeyPress(KeySym keysym, unsigned int state) +void BufferView::Pimpl::workAreaKeyPress(KeySym keysym, key_modifier::state state) { bv_->owner()->getLyXFunc()->processKeySym(keysym, state); } -void BufferView::Pimpl::workAreaMotionNotify(int x, int y, unsigned int state) +void BufferView::Pimpl::workAreaMotionNotify(int x, int y, mouse_button::state state) { // Only use motion with button 1 - if (!(state & Button1MotionMask)) + if (!(state & mouse_button::button1)) return; if (!buffer_ || !screen_.get()) return; @@ -531,135 +561,156 @@ void BufferView::Pimpl::workAreaMotionNotify(int x, int y, unsigned int state) cursor.par(), cursor.pos()); int width = bv_->theLockingInset()->width(bv_, font); int inset_x = font.isVisibleRightToLeft() - ? cursor.x() - width : cursor.x(); + ? cursor.ix() - width : cursor.ix(); int start_x = inset_x + bv_->theLockingInset()->scroll(); bv_->theLockingInset()-> insetMotionNotify(bv_, x - start_x, - y - cursor.y() + bv_->text->first, + y - cursor.iy() + bv_->text->first_y, state); return; } - + /* 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) return; - + screen_->hideCursor(); +#if 0 + int y_before = bv_->text->cursor.y(); +#endif + Row * cursorrow = bv_->text->cursor.row(); + bv_->text->setCursorFromCoordinates(bv_, x, 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 (y >= int(workarea_.height())) { + bv_->text->cursorDown(bv_, false); + } else if (y < 0) { + bv_->text->cursorUp(bv_, false); + } + } - bv_->text->setCursorFromCoordinates(bv_, x, y + bv_->text->first); - if (!bv_->text->selection.set()) update(bv_->text, BufferView::UPDATE); // Maybe an empty line was deleted - + bv_->text->setSelection(bv_); screen_->toggleToggle(bv_->text, bv_); fitCursor(); -#if 0 - screen_->showCursor(bv_->text, bv_); -#else showCursor(); -#endif } // Single-click on work area void BufferView::Pimpl::workAreaButtonPress(int xpos, int ypos, - unsigned int button) + mouse_button::state button) { - if (!buffer_ || !screen_.get()) return; - - Inset * inset_hit = checkInsetHit(bv_->text, xpos, ypos, button); + if (!buffer_ || !screen_.get()) + return; // ok ok, this is a hack. - if (button == 4 || button == 5) { - switch (button) { - case 4: - scrollUp(lyxrc.wheel_jump); // default 100, set in lyxrc - break; - case 5: - scrollDown(lyxrc.wheel_jump); - break; - } + + if (button == mouse_button::button4) { + scrollUp(lyxrc.wheel_jump); + // 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). + return; + } else if (button == mouse_button::button5) { + scrollDown(lyxrc.wheel_jump); + // 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). + return; + } + + Inset * inset_hit = checkInsetHit(bv_->text, xpos, ypos); + + // 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 (button == mouse_button::button2 && bv_->getLyXText()->selection.set()) { + owner_->getLyXFunc()->dispatch(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()) { bv_->theLockingInset()-> - insetButtonPress(bv_, - xpos, ypos, - button); + insetButtonPress(bv_,xpos, ypos,button); return; } else { bv_->unlockInset(bv_->theLockingInset()); } } - + if (!inset_hit) selection_possible = true; screen_->hideCursor(); - int const screen_first = bv_->text->first; - - // Middle button press pastes if we have a selection - bool paste_internally = false; - if (button == 2 - && bv_->text->selection.set()) { - owner_->getLyXFunc()->dispatch(LFUN_COPY); - paste_internally = true; - } - // Clear the selection screen_->toggleSelection(bv_->text, bv_); bv_->text->clearSelection(); bv_->text->fullRebreak(bv_); -#if 0 - screen_->update(bv_->text, bv_); -#else update(); -#endif updateScrollbar(); - + // Single left click in math inset? - if ((inset_hit != 0) && - (inset_hit->editable()==Inset::HIGHLY_EDITABLE)) { + if (isHighlyEditableInset(inset_hit)) { // Highly editable inset, like math UpdatableInset * inset = static_cast(inset_hit); selection_possible = false; owner_->updateLayoutChoice(); owner_->message(inset->editMessage()); + //inset->edit(bv_, xpos, ypos, 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; + } inset->insetButtonPress(bv_, xpos, ypos, button); - inset->edit(bv_, xpos, ypos, button); return; - } - + } + // I'm not sure we should continue here if we hit an inset (Jug20020403) + // Right click on a footnote flag opens float menu - if (button == 3) { + if (button == mouse_button::button3) { selection_possible = false; return; } - + if (!inset_hit) // otherwise it was already set in checkInsetHit(...) bv_->text->setCursorFromCoordinates(bv_, xpos, ypos + screen_first); finishUndo(); bv_->text->selection.cursor = bv_->text->cursor; bv_->text->cursor.x_fix(bv_->text->cursor.x()); - + owner_->updateLayoutChoice(); if (fitCursor()) { selection_possible = false; } - + // Insert primary selection with middle mouse // if there is a local selection in the current buffer, // insert this - if (button == 2) { + if (button == mouse_button::button2) { if (paste_internally) owner_->getLyXFunc()->dispatch(LFUN_PASTE); else @@ -671,37 +722,35 @@ void BufferView::Pimpl::workAreaButtonPress(int xpos, int ypos, } -void BufferView::Pimpl::doubleClick(int /*x*/, int /*y*/, unsigned int button) +void BufferView::Pimpl::doubleClick(int /*x*/, int /*y*/, mouse_button::state button) { - // select a word if (!buffer_) - return; + return; LyXText * text = bv_->getLyXText(); if (text->bv_owner && bv_->theLockingInset()) - return; + return; - if (screen_.get() && button == 1) { - if (text->bv_owner) { - screen_->hideCursor(); - screen_->toggleSelection(text, bv_); - text->selectWord(bv_, LyXText::WHOLE_WORD_STRICT); - screen_->toggleSelection(text, bv_, false); - } else { - text->selectWord(bv_, LyXText::WHOLE_WORD_STRICT); - } - /* This will fit the cursor on the screen - * if necessary */ - update(text, BufferView::SELECT|BufferView::FITCUR); + if (screen_.get() && button == mouse_button::button1) { + if (text->bv_owner) { + screen_->hideCursor(); + screen_->toggleSelection(text, bv_); + text->selectWord(bv_, LyXText::WHOLE_WORD_STRICT); + screen_->toggleSelection(text, bv_, false); + } else { + text->selectWord(bv_, LyXText::WHOLE_WORD_STRICT); + } + /* This will fit the cursor on the screen + * if necessary */ + update(text, BufferView::SELECT|BufferView::FITCUR); } } -void BufferView::Pimpl::tripleClick(int /*x*/, int /*y*/, unsigned int button) +void BufferView::Pimpl::tripleClick(int /*x*/, int /*y*/, mouse_button::state button) { - // select a line - if (buffer_) + if (!buffer_) return; LyXText * text = bv_->getLyXText(); @@ -709,14 +758,18 @@ void BufferView::Pimpl::tripleClick(int /*x*/, int /*y*/, unsigned int button) if (text->bv_owner && bv_->theLockingInset()) return; - if (screen_.get() && (button == 1)) { - screen_->hideCursor(); - screen_->toggleSelection(text, bv_); + if (screen_.get() && (button == mouse_button::button1)) { + if (text->bv_owner) { + screen_->hideCursor(); + screen_->toggleSelection(text, bv_); + } text->cursorHome(bv_); text->selection.cursor = text->cursor; text->cursorEnd(bv_); text->setSelection(bv_); - screen_->toggleSelection(text, bv_, false); + if (text->bv_owner) { + screen_->toggleSelection(text, bv_, false); + } /* This will fit the cursor on the screen * if necessary */ update(text, BufferView::SELECT|BufferView::FITCUR); @@ -724,6 +777,44 @@ void BufferView::Pimpl::tripleClick(int /*x*/, int /*y*/, unsigned int button) } +void BufferView::Pimpl::selectionRequested() +{ + static string sel; + + if (!available()) + return; + + LyXText * text = bv_->getLyXText(); + + if (text->selection.set() && + (!bv_->text->xsel_cache.set() || + text->selection.start != bv_->text->xsel_cache.start || + text->selection.end != bv_->text->xsel_cache.end)) + { + bv_->text->xsel_cache = text->selection; + sel = text->selectionAsString(bv_->buffer(), false); + } else if (!text->selection.set()) { + sel = string(); + bv_->text->xsel_cache.set(false); + } + if (!sel.empty()) { + workarea_.putClipboard(sel); + } +} + + +void BufferView::Pimpl::selectionLost() +{ + if (active() && available()) { + hideCursor(); + toggleSelection(); + bv_->getLyXText()->clearSelection(); + showCursor(); + bv_->text->xsel_cache.set(false); + } +} + + void BufferView::Pimpl::enterView() { if (active() && available()) { @@ -743,40 +834,62 @@ void BufferView::Pimpl::leaveView() void BufferView::Pimpl::workAreaButtonRelease(int x, int y, - unsigned int button) + mouse_button::state button) { - if (!buffer_ || !screen_.get()) return; + // do nothing if we used the mouse wheel + if (!buffer_ || !screen_.get() || button == mouse_button::button4 || button == mouse_button::button5) + return; // 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. - Inset * inset_hit = checkInsetHit(bv_->text, x, y, button); + Inset * inset_hit = checkInsetHit(bv_->text, x, y); if (bv_->theLockingInset()) { // We are in inset locking mode. /* LyX does a kind of work-area grabbing for insets. - Only a ButtonPress Event outside the inset will + Only a ButtonPress Event outside the inset will force a insetUnlock. */ bv_->theLockingInset()-> insetButtonRelease(bv_, x, y, button); return; } - + selection_possible = false; - - if (button == 2) + + if (button == mouse_button::button2) return; + // finish selection + if (button == mouse_button::button1) { + workarea_.haveSelection(bv_->getLyXText()->selection.set()); + } + setState(); owner_->showState(); + owner_->updateMenubar(); + owner_->updateToolbar(); // Did we hit an editable inset? if (inset_hit) { - // Inset like error, notes and figures 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 (bv_->getLyXText()->selection.set()) + return; + // CHECK fix this proper in 0.13 + // well, maybe 13.0 !!!!!!!!! // Following a ref shouldn't issue // a push on the undo-stack @@ -797,120 +910,121 @@ void BufferView::Pimpl::workAreaButtonRelease(int x, int y, owner_->message(inset_hit->editMessage()); - if (inset_hit->editable()==Inset::HIGHLY_EDITABLE) { + if (isHighlyEditableInset(inset_hit)) { // Highly editable inset, like math UpdatableInset *inset = (UpdatableInset *)inset_hit; inset->insetButtonRelease(bv_, x, y, button); } else { inset_hit->insetButtonRelease(bv_, x, y, button); + // 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) inset_hit->edit(bv_, x, y, button); } return; } - // check whether we want to open a float - if (bv_->text) { - bool hit = false; - char c = ' '; - if (bv_->text->cursor.pos() < - bv_->text->cursor.par()->size()) { - c = bv_->text->cursor.par()-> - getChar(bv_->text->cursor.pos()); - } - if (bv_->text->cursor.pos() - 1 >= 0) { - c = bv_->text->cursor.par()-> - getChar(bv_->text->cursor.pos() - 1); - } - if (hit == true) { - selection_possible = false; - return; - } - } - // Maybe we want to edit a bibitem ale970302 - if (bv_->text->cursor.par()->bibkey && x < 20 + - bibitemMaxWidth(bv_, textclasslist. - TextClass(buffer_-> - params.textclass).defaultfont())) { - bv_->text->cursor.par()->bibkey->edit(bv_, 0, 0, 0); + if (bv_->text->cursor.par()->bibkey && x < 20 + + bibitemMaxWidth(bv_, textclasslist[buffer_->params.textclass].defaultfont())) { + bv_->text->cursor.par()->bibkey->edit(bv_, 0, 0, mouse_button::none); } return; } -/* - * Returns an inset if inset was hit. 0 otherwise. - * If hit, the coordinates are changed relative to the inset. - * Otherwise coordinates are not changed, and false is returned. - */ -Inset * BufferView::Pimpl::checkInsetHit(LyXText * text, int & x, int & y, - unsigned int /* button */) +Box BufferView::Pimpl::insetDimensions(LyXText const & text, + LyXCursor const & cursor) const +{ + Paragraph /*const*/ & par = *cursor.par(); + pos_type const pos = cursor.pos(); + + lyx::Assert(par.getInset(pos)); + + Inset const & inset(*par.getInset(pos)); + + LyXFont const & font = text.getFont(buffer_, &par, pos); + + int const width = inset.width(bv_, font); + int const inset_x = font.isVisibleRightToLeft() + ? (cursor.ix() - width) : cursor.ix(); + + return Box( + inset_x + inset.scroll(), + inset_x + width, + cursor.iy() - inset.ascent(bv_, font), + cursor.iy() + inset.descent(bv_, font)); +} + + +Inset * BufferView::Pimpl::checkInset(LyXText const & text, + LyXCursor const & cursor, + int & x, int & y) const +{ + pos_type const pos(cursor.pos()); + Paragraph /*const*/ & par(*cursor.par()); + + if (pos >= par.size() || !par.isInset(pos)) { + return 0; + } + + Inset /*const*/ * inset = par.getInset(pos); + + if (!isEditableInset(inset)) { + return 0; + } + + Box b(insetDimensions(text, cursor)); + + 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; +} + + +Inset * BufferView::Pimpl::checkInsetHit(LyXText * text, int & x, int & y) { if (!screen_.get()) return 0; - - int y_tmp = y + text->first; - + + int y_tmp = y + text->first_y; + LyXCursor cursor; text->setCursorFromCoordinates(bv_, cursor, x, y_tmp); - text->setCursor(bv_, cursor, cursor.par(),cursor.pos(),true); + Inset * inset(checkInset(*text, cursor, x, y_tmp)); - if (cursor.pos() < cursor.par()->size() - && cursor.par()->getChar(cursor.pos()) == Paragraph::META_INSET - && cursor.par()->getInset(cursor.pos()) - && cursor.par()->getInset(cursor.pos())->editable()) { + if (inset) { + y = y_tmp; + return inset; + } - // Check whether the inset really was hit - Inset * tmpinset = cursor.par()->getInset(cursor.pos()); - LyXFont font = text->getFont(buffer_, - cursor.par(), cursor.pos()); - int const width = tmpinset->width(bv_, font); - int const inset_x = font.isVisibleRightToLeft() - ? cursor.x() - width : cursor.x(); - int const start_x = inset_x + tmpinset->scroll(); - int const end_x = inset_x + width; - - if (x > start_x && x < end_x - && y_tmp > cursor.y() - tmpinset->ascent(bv_, font) - && y_tmp < cursor.y() + tmpinset->descent(bv_, font)) { - text->setCursor(bv_, cursor.par(),cursor.pos(), true); - x = x - start_x; - // The origin of an inset is on the baseline - y = y_tmp - (text->cursor.y()); - return tmpinset; - } + // look at previous position + + if (cursor.pos() == 0) { + return 0; } - if ((cursor.pos() - 1 >= 0) && - (cursor.par()->getChar(cursor.pos()-1) == Paragraph::META_INSET) && - (cursor.par()->getInset(cursor.pos() - 1)) && - (cursor.par()->getInset(cursor.pos() - 1)->editable())) { - Inset * tmpinset = cursor.par()->getInset(cursor.pos()-1); - LyXFont font = text->getFont(buffer_, cursor.par(), - cursor.pos() - 1); - int const width = tmpinset->width(bv_, font); - int const inset_x = font.isVisibleRightToLeft() - ? cursor.x() : cursor.x() - width; - int const start_x = inset_x + tmpinset->scroll(); - int const end_x = inset_x + width; - - if (x > start_x && x < end_x - && y_tmp > cursor.y() - tmpinset->ascent(bv_, font) - && y_tmp < cursor.y() + tmpinset->descent(bv_, font)) { -#if 0 - if (move_cursor && (tmpinset != bv_->theLockingInset())) -#endif - text->setCursor(bv_, cursor.par(), - cursor.pos() - 1, true); - x = x - start_x; - // The origin of an inset is on the baseline - y = y_tmp - (text->cursor.y()); - return tmpinset; - } + // move back one + text->setCursor(bv_, cursor, cursor.par(), cursor.pos() - 1, true); + + inset = checkInset(*text, cursor, x, y_tmp); + if (inset) { + y = y_tmp; } - return 0; + return inset; } @@ -939,6 +1053,7 @@ void BufferView::Pimpl::workAreaExpose() if (lyxerr.debugging()) textcache.show(lyxerr, "Expose delete all"); textcache.clear(); + buffer_->resizeInsets(bv_); } else if (heightChange) { // Rebuild image of current screen updateScreen(); @@ -971,13 +1086,20 @@ void BufferView::Pimpl::update() LyXText::text_status st = bv_->text->status(); screen_->update(bv_->text, bv_); bool fitc = false; - while(bv_->text->status() == LyXText::CHANGED_IN_DRAW) { - if (bv_->text->fullRebreak(bv_)) { - st = LyXText::NEED_MORE_REFRESH; - bv_->text->setCursor(bv_, bv_->text->cursor.par(), - bv_->text->cursor.pos()); - fitc = true; + while (bv_->text->status() == LyXText::CHANGED_IN_DRAW) { + bv_->text->fullRebreak(bv_); + st = LyXText::NEED_MORE_REFRESH; + bv_->text->setCursor(bv_, bv_->text->cursor.par(), + bv_->text->cursor.pos()); + if (bv_->text->selection.set()) { + bv_->text->setCursor(bv_, bv_->text->selection.start, + bv_->text->selection.start.par(), + bv_->text->selection.start.pos()); + bv_->text->setCursor(bv_, bv_->text->selection.end, + bv_->text->selection.end.par(), + bv_->text->selection.end.pos()); } + fitc = true; bv_->text->status(bv_, st); screen_->update(bv_->text, bv_); } @@ -993,7 +1115,7 @@ void BufferView::Pimpl::update() // -3 - update // -2 - update, move sel_cursor if selection, fitcursor // -1 - update, move sel_cursor if selection, fitcursor, mark dirty -// 0 - update, move sel_cursor if selection, fitcursor +// 0 - update, move sel_cursor if selection, fitcursor // 1 - update, move sel_cursor if selection, fitcursor, mark dirty // 3 - update, move sel_cursor if selection // @@ -1013,7 +1135,7 @@ void BufferView::Pimpl::update() // UPDATE = 0, // SELECT = 1, // FITCUR = 2, -// CHANGE = 4 +// CHANGE = 4 // }; // // UPDATE_ONLY = UPDATE; @@ -1039,11 +1161,11 @@ void BufferView::Pimpl::update(LyXText * text, BufferView::UpdateCodes f) if (text->inset_owner) { text->inset_owner->setUpdateStatus(bv_, InsetText::NONE); - updateInset(text->inset_owner, true); + updateInset(text->inset_owner, false); } else { update(); } - + if ((f & FITCUR)) { fitCursor(); } @@ -1057,91 +1179,139 @@ void BufferView::Pimpl::update(LyXText * text, BufferView::UpdateCodes f) // Callback for cursor timer void BufferView::Pimpl::cursorToggle() { - // Quite a nice place for asyncron Inset updating, isn't it? - // Actually no! This is run even if no buffer exist... so (Lgb) if (!buffer_) { cursor_timeout.restart(); return; } - - int status = 1; - int const pid = waitpid(static_cast(0), &status, WNOHANG); - if (pid == -1) // error find out what is wrong - ; // ignore it for now. - else if (pid > 0) - sigchldchecker(pid, &status); - updatelist.update(bv_); - if (!screen_.get()) { cursor_timeout.restart(); return; } + /* FIXME */ + extern void reapSpellchecker(void); + reapSpellchecker(); + if (!bv_->theLockingInset()) { screen_->cursorToggle(bv_); } else { bv_->theLockingInset()->toggleInsetCursor(bv_); } - + cursor_timeout.restart(); } void BufferView::Pimpl::cursorPrevious(LyXText * text) { - if (!text->cursor.row()->previous()) + if (!text->cursor.row()->previous()) { + if (text->first_y > 0) { + int new_y = bv_->text->first_y - workarea_.height(); + screen_->draw(bv_->text, bv_, new_y < 0 ? 0 : new_y); + updateScrollbar(); + } return; - - int y = text->first; - if (text->inset_owner) - y += bv_->text->first; + } + + int y = text->first_y; Row * cursorrow = text->cursor.row(); - text->setCursorFromCoordinates(bv_, bv_->text->cursor.x_fix(), y); + + text->setCursorFromCoordinates(bv_, text->cursor.x_fix(), y); finishUndo(); - // This is to allow jumping over large insets - if ((cursorrow == text->cursor.row())) - text->cursorUp(bv_); - - if (text->inset_owner || - text->cursor.row()->height() < workarea_.height()) - screen_->draw(bv_->text, bv_, - text->cursor.y() - - text->cursor.row()->baseline() - + text->cursor.row()->height() - - workarea_.height() + 1 ); + + 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 - workarea_.height(); + } else { + if (text->inset_owner) { + new_y = bv_->text->cursor.iy() + + bv_->theLockingInset()->insetInInsetY() + y + + text->cursor.row()->height() + - workarea_.height() + 1; + } else { + new_y = text->cursor.y() + - text->cursor.row()->baseline() + + text->cursor.row()->height() + - workarea_.height() + 1; + } + } + screen_->draw(bv_->text, bv_, new_y < 0 ? 0 : new_y); + if (text->cursor.row()->previous()) { + LyXCursor cur; + text->setCursor(bv_, cur, text->cursor.row()->previous()->par(), + text->cursor.row()->previous()->pos(), false); + if (cur.y() > text->first_y) { + text->cursorUp(bv_, true); + } + } updateScrollbar(); } void BufferView::Pimpl::cursorNext(LyXText * text) { - if (!text->cursor.row()->next()) + if (!text->cursor.row()->next()) { + int y = text->cursor.y() - text->cursor.row()->baseline() + + text->cursor.row()->height(); + if (y > int(text->first_y + workarea_.height())) { + screen_->draw(bv_->text, bv_, + bv_->text->first_y + workarea_.height()); + updateScrollbar(); + } return; - - int y = text->first + workarea_.height(); -// if (text->inset_owner) -// y += bv_->text->first; + } + + int y = text->first_y + workarea_.height(); + if (text->inset_owner && !text->first_y) { + y -= (bv_->text->cursor.iy() + - bv_->text->first_y + + bv_->theLockingInset()->insetInInsetY()); + } text->getRowNearY(y); - + Row * cursorrow = text->cursor.row(); text->setCursorFromCoordinates(bv_, text->cursor.x_fix(), y); // + workarea_->height()); finishUndo(); - // This is to allow jumping over large insets - if ((cursorrow == bv_->text->cursor.row())) - text->cursorDown(bv_); - - if (text->inset_owner || - text->cursor.row()->height() < workarea_.height()) - screen_->draw(bv_->text, bv_, text->cursor.y() - - text->cursor.row()->baseline()); + 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 + workarea_.height(); + } else { + if (text->inset_owner) { + new_y = bv_->text->cursor.iy() + + bv_->theLockingInset()->insetInInsetY() + + y - text->cursor.row()->baseline(); + } else { + new_y = text->cursor.y() - text->cursor.row()->baseline(); + } + } + screen_->draw(bv_->text, bv_, new_y); + if (text->cursor.row()->next()) { + LyXCursor cur; + text->setCursor(bv_, cur, text->cursor.row()->next()->par(), + text->cursor.row()->next()->pos(), false); + if (cur.y() < int(text->first_y + workarea_.height())) { + text->cursorDown(bv_, true); + } + } updateScrollbar(); } bool BufferView::Pimpl::available() const { - if (buffer_ && bv_->text) return true; + if (buffer_ && bv_->text) + return true; return false; } @@ -1179,9 +1349,9 @@ void BufferView::Pimpl::restorePosition(unsigned int i) if (fname != buffer_->fileName()) { Buffer * b = bufferlist.exists(fname) ? - bufferlist.getBuffer(fname) : + bufferlist.getBuffer(fname) : bufferlist.loadLyXFile(fname); // don't ask, just load it - if (b != 0 ) buffer(b); + if (b != 0) buffer(b); } Paragraph * par = buffer_->getParFromID(saved_positions[i].par_id); @@ -1215,7 +1385,10 @@ void BufferView::Pimpl::setState() return; LyXText * text = bv_->getLyXText(); - if (text->real_current_font.isRightToLeft()) { + if (text->real_current_font.isRightToLeft() + && !(bv_->theLockingInset() + && bv_->theLockingInset()->lyxCode()== Inset::ERT_CODE)) + { if (owner_->getIntl()->keymap == Intl::PRIMARY) owner_->getIntl()->KeyMapSec(); } else { @@ -1225,6 +1398,7 @@ void BufferView::Pimpl::setState() } +#if 0 void BufferView::Pimpl::insetSleep() { if (bv_->theLockingInset() && !inset_slept) { @@ -1242,6 +1416,7 @@ void BufferView::Pimpl::insetWakeup() inset_slept = false; } } +#endif void BufferView::Pimpl::insetUnlock() @@ -1274,7 +1449,7 @@ bool BufferView::Pimpl::active() const } -bool BufferView::Pimpl::belowMouse() const +bool BufferView::Pimpl::belowMouse() const { return workarea_.belowMouse(); } @@ -1319,7 +1494,7 @@ void BufferView::Pimpl::toggleToggle() } -void BufferView::Pimpl::center() +void BufferView::Pimpl::center() { beforeChange(bv_->text); if (bv_->text->cursor.y() > static_cast((workarea_.height() / 2))) { @@ -1332,22 +1507,25 @@ void BufferView::Pimpl::center() } -void BufferView::Pimpl::pasteClipboard(bool asPara) +void BufferView::Pimpl::pasteClipboard(bool asPara) { - if (!buffer_) return; + if (!buffer_) + return; screen_->hideCursor(); beforeChange(bv_->text); - + string const clip(workarea_.getClipboard()); - - if (clip.empty()) return; + + if (clip.empty()) + return; if (asPara) { - bv_->text->insertStringAsParagraphs(bv_, clip); + bv_->getLyXText()->insertStringAsParagraphs(bv_, clip); } else { - bv_->text->insertStringAsLines(bv_, clip); + bv_->getLyXText()->insertStringAsLines(bv_, clip); } + bv_->getLyXText()->clearSelection(); update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); } @@ -1365,18 +1543,32 @@ void BufferView::Pimpl::stuffClipboard(string const & stuff) const inline -void BufferView::Pimpl::moveCursorUpdate(bool selecting) +void BufferView::Pimpl::moveCursorUpdate(bool selecting, bool fitcur) { LyXText * lt = bv_->getLyXText(); - + if (selecting || lt->selection.mark()) { lt->setSelection(bv_); if (lt->bv_owner) toggleToggle(); + else + updateInset(lt->inset_owner, false); } - update(lt, BufferView::SELECT|BufferView::FITCUR); - showCursor(); - + if (lt->bv_owner) { + if (fitcur) + update(lt, BufferView::SELECT|BufferView::FITCUR); + else + update(lt, BufferView::SELECT); + showCursor(); + } else if (bv_->text->status() != LyXText::UNCHANGED) { + bv_->theLockingInset()->hideInsetCursor(bv_); + update(bv_->text, BufferView::SELECT|BufferView::FITCUR); + showCursor(); + } + + if (!lt->selection.set()) + workarea_.haveSelection(false); + /* ---> Everytime the cursor is moved, show the current font state. */ // should this too me moved out of this func? //owner->showState(); @@ -1405,7 +1597,7 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) string initpath = lyxrc.document_path; if (available()) { - string const trypath = owner_->buffer()->filepath; + string const trypath = owner_->buffer()->filePath(); // If directory is writeable, use this as default. if (IsDirWriteable(trypath)) initpath = trypath; @@ -1414,15 +1606,15 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) FileDialog fileDlg(bv_->owner(), _("Select LyX document to insert"), LFUN_FILE_INSERT, - make_pair(string(_("Documents")), + make_pair(string(_("Documents|#o#O")), string(lyxrc.document_path)), - make_pair(string(_("Examples")), + make_pair(string(_("Examples|#E#e")), string(AddPath(system_lyxdir, "examples")))); FileDialog::Result result = fileDlg.Select(initpath, _("*.lyx| LyX Documents (*.lyx)")); - + if (result.first == FileDialog::Later) return; @@ -1440,7 +1632,7 @@ void BufferView::Pimpl::MenuInsertLyXFile(string const & filen) filename = FileSearch(string(), filename, "lyx"); string const disp_fn(MakeDisplayPath(filename)); - + ostringstream s1; s1 << _("Inserting document") << ' ' << disp_fn << " ..."; @@ -1464,7 +1656,9 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) { lyxerr[Debug::ACTION] << "BufferView::Pimpl::Dispatch: action[" << action <<"] arg[" << argument << "]" << endl; - + + LyXTextClass const & tclass = textclasslist[buffer_->params.textclass]; + switch (action) { // --- Misc ------------------------------------------- case LFUN_APPENDIX: @@ -1485,12 +1679,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) InsetCommandParams p; p.setCmdName("tableofcontents"); Inset * inset = new InsetTOC(p); - if (!insertInset(inset, "Standard")) + if (!insertInset(inset, tclass.defaultLayoutName())) delete inset; break; } - - case LFUN_TABULAR_FEATURE: + case LFUN_SCROLL_INSET: // this is not handled here as this funktion is only aktive // if we have a locking_inset and that one is (or contains) @@ -1509,41 +1702,42 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) } break; } - + case LFUN_PASTE: bv_->paste(); setState(); break; - + case LFUN_PASTESELECTION: { - bool asPara = false; - if (argument == "paragraph") asPara = true; + bool asPara = false; + if (argument == "paragraph") + asPara = true; pasteClipboard(asPara); } break; - + case LFUN_CUT: bv_->cut(); break; - + case LFUN_COPY: bv_->copy(); break; - + case LFUN_LAYOUT_COPY: bv_->copyEnvironment(); break; - + case LFUN_LAYOUT_PASTE: bv_->pasteEnvironment(); setState(); break; - + case LFUN_GOTOERROR: gotoInset(Inset::ERROR_CODE, false); break; - + case LFUN_GOTONOTE: gotoInset(Inset::IGNORE_CODE, false); break; @@ -1560,15 +1754,15 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_HYPHENATION: specialChar(InsetSpecialChar::HYPHENATION); break; - + case LFUN_LIGATURE_BREAK: specialChar(InsetSpecialChar::LIGATURE_BREAK); break; - + case LFUN_LDOTS: specialChar(InsetSpecialChar::LDOTS); break; - + case LFUN_END_OF_SENTENCE: specialChar(InsetSpecialChar::END_OF_SENTENCE); break; @@ -1576,33 +1770,27 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_MENU_SEPARATOR: specialChar(InsetSpecialChar::MENU_SEPARATOR); break; - + case LFUN_HFILL: hfill(); break; - - case LFUN_DEPTH: - changeDepth(bv_, bv_->getLyXText(), 0); - break; - + case LFUN_DEPTH_MIN: changeDepth(bv_, bv_->getLyXText(), -1); break; - + case LFUN_DEPTH_PLUS: changeDepth(bv_, bv_->getLyXText(), 1); break; - + case LFUN_FREE: owner_->getDialogs()->setUserFreeFont(); break; case LFUN_FILE_INSERT: - { MenuInsertLyXFile(argument); - } - break; - + break; + case LFUN_FILE_INSERT_ASCII_PARA: InsertAsciiFile(bv_, argument, true); break; @@ -1610,45 +1798,64 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_FILE_INSERT_ASCII: InsertAsciiFile(bv_, argument, false); break; - + case LFUN_LAYOUT: { lyxerr[Debug::INFO] << "LFUN_LAYOUT: (arg) " << 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 (argument.empty()) { + owner_->getLyXFunc()->setErrorMessage( + _("LyX function 'layout' needs an argument.")); + break; + } + // Derive layout number from given argument (string) - // and current buffer's textclass (number). */ - LyXTextClassList::ClassList::size_type tclass = - buffer_->params.textclass; - pair layout = - textclasslist.NumberOfLayout(tclass, argument); + // and current buffer's textclass (number). */ + bool hasLayout = tclass.hasLayout(argument); + string layout = argument; // If the entry is obsolete, use the new one instead. - if (layout.first) { - string obs = textclasslist.Style(tclass,layout.second) - .obsoleted_by(); - if (!obs.empty()) - layout = - textclasslist.NumberOfLayout(tclass, obs); + if (hasLayout) { + string const & obs = tclass[layout].obsoleted_by(); + if (!obs.empty()) + layout = obs; } - // see if we found the layout number: - if (!layout.first) { + if (!hasLayout) { owner_->getLyXFunc()->setErrorMessage( string(N_("Layout ")) + argument + N_(" not known")); break; } - if (current_layout != layout.second) { - LyXText * lt = bv_->getLyXText(); + bool change_layout = (current_layout != layout); + LyXText * lt = bv_->getLyXText(); + if (!change_layout && lt->selection.set() && + lt->selection.start.par() != lt->selection.end.par()) + { + Paragraph * spar = lt->selection.start.par(); + Paragraph * epar = lt->selection.end.par()->next(); + while(spar != epar) { + if (spar->layout() != current_layout) { + change_layout = true; + break; + } + } + } + if (change_layout) { hideCursor(); - current_layout = layout.second; + current_layout = layout; update(lt, BufferView::SELECT | BufferView::FITCUR); - lt->setLayout(bv_, layout.second); - owner_->setLayout(layout.second); + lt->setLayout(bv_, layout); + owner_->setLayout(layout); update(lt, BufferView::SELECT | BufferView::FITCUR @@ -1673,50 +1880,50 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) bold(bv_); owner_->showState(); break; - + case LFUN_NOUN: noun(bv_); owner_->showState(); break; - + case LFUN_CODE: code(bv_); owner_->showState(); break; - + case LFUN_SANS: sans(bv_); owner_->showState(); break; - + case LFUN_ROMAN: roman(bv_); owner_->showState(); break; - + case LFUN_DEFAULT: styleReset(bv_); owner_->showState(); break; - + case LFUN_UNDERLINE: underline(bv_); owner_->showState(); break; - + case LFUN_FONT_SIZE: fontSize(bv_, argument); owner_->showState(); break; - + case LFUN_FONT_STATE: owner_->getLyXFunc()->setMessage(currentState(bv_)); break; - + case LFUN_UPCASE_WORD: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT | BufferView::FITCUR); @@ -1729,11 +1936,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::CHANGE); } break; - + case LFUN_LOWCASE_WORD: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->changeCase(bv_, LyXText::text_lowercase); if (lt->inset_owner) @@ -1744,11 +1951,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::CHANGE); } break; - + case LFUN_CAPITALIZE_WORD: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->changeCase(bv_, LyXText::text_capitalization); if (lt->inset_owner) @@ -1763,7 +1970,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_TRANSPOSE_CHARS: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->transposeChars(*bv_); if (lt->inset_owner) @@ -1774,12 +1981,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::CHANGE); } break; - - + + case LFUN_INSERT_LABEL: MenuInsertLabel(bv_, argument); break; - + case LFUN_REF_INSERT: if (argument.empty()) { InsetCommandParams p("ref"); @@ -1808,29 +2015,29 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) { string label(argument); if (label.empty()) { - InsetRef * inset = + InsetRef * inset = static_cast(getInsetByCode(Inset::REF_CODE)); if (inset) { - label = inset->getContents(); + label = inset->getContents(); savePosition(0); } } - + if (!label.empty()) { //bv_->savePosition(0); if (!bv_->gotoLabel(label)) - WriteAlert(_("Error"), - _("Couldn't find this label"), + Alert::alert(_("Error"), + _("Couldn't find this label"), _("in current document.")); } } break; - + // --- Cursor Movements ----------------------------- case LFUN_RIGHT: { LyXText * lt = bv_->getLyXText(); - + bool is_rtl = lt->cursor.par()->isRightToLeftPar(buffer_->params); if (!lt->selection.mark()) beforeChange(lt); @@ -1838,10 +2045,8 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) if (is_rtl) lt->cursorLeft(bv_, false); if (lt->cursor.pos() < lt->cursor.par()->size() - && lt->cursor.par()->getChar(lt->cursor.pos()) - == Paragraph::META_INSET - && lt->cursor.par()->getInset(lt->cursor.pos()) - && lt->cursor.par()->getInset(lt->cursor.pos())->editable() == Inset::HIGHLY_EDITABLE){ + && lt->cursor.par()->isInset(lt->cursor.pos()) + && isHighlyEditableInset(lt->cursor.par()->getInset(lt->cursor.pos()))) { Inset * tmpinset = lt->cursor.par()->getInset(lt->cursor.pos()); owner_->getLyXFunc()->setMessage(tmpinset->editMessage()); if (is_rtl) @@ -1857,7 +2062,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_LEFT: { // This is soooo ugly. Isn`t it possible to make @@ -1872,12 +2077,8 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) lt->cursorLeft(bv_, false); if ((is_rtl || cur != lt->cursor) && // only if really moved! lt->cursor.pos() < lt->cursor.par()->size() && - (lt->cursor.par()->getChar(lt->cursor.pos()) == - Paragraph::META_INSET) && - lt->cursor.par()->getInset(lt->cursor.pos()) && - (lt->cursor.par()->getInset(lt->cursor.pos())->editable() - == Inset::HIGHLY_EDITABLE)) - { + lt->cursor.par()->isInset(lt->cursor.pos()) && + isHighlyEditableInset(lt->cursor.par()->getInset(lt->cursor.pos()))) { Inset * tmpinset = lt->cursor.par()->getInset(lt->cursor.pos()); owner_->getLyXFunc()->setMessage(tmpinset->editMessage()); if (is_rtl) @@ -1894,11 +2095,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_UP: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::UPDATE); @@ -1908,11 +2109,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_DOWN: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::UPDATE); @@ -1926,7 +2127,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_UP_PARAGRAPH: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::UPDATE); @@ -1936,11 +2137,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_DOWN_PARAGRAPH: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::UPDATE); @@ -1950,39 +2151,39 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_PRIOR: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::UPDATE); cursorPrevious(lt); finishUndo(); - moveCursorUpdate(false); + moveCursorUpdate(false, false); owner_->showState(); } break; - + case LFUN_NEXT: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::UPDATE); cursorNext(lt); finishUndo(); - moveCursorUpdate(false); + moveCursorUpdate(false, false); owner_->showState(); } break; - + case LFUN_HOME: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::SELECT|BufferView::FITCUR); @@ -1992,11 +2193,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_END: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, @@ -2007,12 +2208,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_SHIFT_TAB: case LFUN_TAB: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, @@ -2023,11 +2224,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_WORDRIGHT: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::SELECT|BufferView::FITCUR); @@ -2040,11 +2241,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_WORDLEFT: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, BufferView::SELECT|BufferView::FITCUR); @@ -2057,11 +2258,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_BEGINNINGBUF: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, @@ -2072,11 +2273,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_ENDBUF: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.mark()) beforeChange(lt); update(lt, @@ -2087,12 +2288,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + /* cursor selection ---------------------------- */ case LFUN_RIGHTSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); if (lt->cursor.par()->isRightToLeftPar(buffer_->params)) @@ -2104,11 +2305,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_LEFTSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); if (lt->cursor.par()->isRightToLeftPar(buffer_->params)) @@ -2120,27 +2321,27 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_UPSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); - lt->cursorUp(bv_); + lt->cursorUp(bv_, true); finishUndo(); moveCursorUpdate(true); owner_->showState(); } break; - + case LFUN_DOWNSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); - lt->cursorDown(bv_); + lt->cursorDown(bv_, true); finishUndo(); moveCursorUpdate(true); owner_->showState(); @@ -2150,7 +2351,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_UP_PARAGRAPHSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->cursorUpParagraph(bv_); @@ -2159,11 +2360,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_DOWN_PARAGRAPHSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->cursorDownParagraph(bv_); @@ -2172,11 +2373,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_PRIORSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); cursorPrevious(lt); finishUndo(); @@ -2184,11 +2385,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_NEXTSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); cursorNext(lt); finishUndo(); @@ -2196,11 +2397,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_HOMESEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->cursorHome(bv_); finishUndo(); @@ -2208,11 +2409,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_ENDSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->cursorEnd(bv_); finishUndo(); @@ -2220,11 +2421,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_WORDRIGHTSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); if (lt->cursor.par()->isRightToLeftPar(buffer_->params)) lt->cursorLeftOneWord(bv_); @@ -2235,11 +2436,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_WORDLEFTSEL: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); if (lt->cursor.par()->isRightToLeftPar(buffer_->params)) lt->cursorRightOneWord(bv_); @@ -2250,11 +2451,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_BEGINNINGBUFSEL: { LyXText * lt = bv_->getLyXText(); - + if (lt->inset_owner) break; update(lt, BufferView::SELECT|BufferView::FITCUR); @@ -2264,11 +2465,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + case LFUN_ENDBUFSEL: { LyXText * lt = bv_->getLyXText(); - + if (lt->inset_owner) break; update(lt, @@ -2291,17 +2492,16 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE); + lt->setCursor(bv_, lt->cursor.par(), lt->cursor.pos()); moveCursorUpdate(false); } break; - + case LFUN_PROTECTEDSPACE: { LyXText * lt = bv_->getLyXText(); - LyXLayout const & style = textclasslist - .Style(buffer_->params.textclass, - lt->cursor.par()->getLayout()); + LyXLayout const & style = tclass[lt->cursor.par()->layout()]; if (style.free_spacing) { lt->insertChar(bv_, ' '); @@ -2310,12 +2510,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::FITCUR | BufferView::CHANGE); } else { - protectedBlank(lt); + specialChar(InsetSpecialChar::PROTECTED_SEPARATOR); } moveCursorUpdate(false); } break; - + case LFUN_SETMARK: { LyXText * lt = bv_->getLyXText(); @@ -2337,7 +2537,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) lt->selection.cursor = lt->cursor; } break; - + case LFUN_DELETE: { LyXText * lt = bv_->getLyXText(); @@ -2353,7 +2553,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) // just comment out the line below... showCursor(); } else { - bv_->cut(); + bv_->cut(false); } moveCursorUpdate(false); owner_->showState(); @@ -2366,7 +2566,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) LyXText * lt = bv_->getLyXText(); // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP. - + LyXCursor cursor = lt->cursor; if (!lt->selection.set()) { @@ -2380,14 +2580,15 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) (bv_, cursor.par()->params().lineTop(), cursor.par()->params().lineBottom(), - cursor.par()->params().pagebreakTop(), + cursor.par()->params().pagebreakTop(), cursor.par()->params().pagebreakBottom(), - VSpace(VSpace::NONE), + VSpace(VSpace::NONE), cursor.par()->params().spaceBottom(), - cursor.par()->params().align(), + cursor.par()->params().spacing(), + cursor.par()->params().align(), cursor.par()->params().labelWidthString(), 0); lt->cursorLeft(bv_); - update(lt, + update(lt, BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE); @@ -2409,7 +2610,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::CHANGE); } } else { - bv_->cut(); + bv_->cut(false); } } break; @@ -2427,7 +2628,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_DELETE_WORD_BACKWARD: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->deleteWordBackward(bv_); update(lt, @@ -2438,12 +2639,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); } break; - + /* -------> Kill to end of line. */ case LFUN_DELETE_LINE_FORWARD: { LyXText * lt = bv_->getLyXText(); - + update(lt, BufferView::SELECT|BufferView::FITCUR); lt->deleteLineForward(bv_); update(lt, @@ -2453,12 +2654,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) moveCursorUpdate(false); } break; - + /* -------> Set mark off. */ case LFUN_MARK_OFF: { LyXText * lt = bv_->getLyXText(); - + beforeChange(lt); update(lt, BufferView::SELECT|BufferView::FITCUR); lt->selection.cursor = lt->cursor; @@ -2470,7 +2671,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_MARK_ON: { LyXText * lt = bv_->getLyXText(); - + beforeChange(lt); lt->selection.mark(true); update(lt, BufferView::SELECT|BufferView::FITCUR); @@ -2478,11 +2679,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->getLyXFunc()->setMessage(N_("Mark on")); } break; - + case LFUN_BACKSPACE: { LyXText * lt = bv_->getLyXText(); - + if (!lt->selection.set()) { if (owner_->getIntl()->getTrans().backspace()) { lt->backspace(bv_); @@ -2496,7 +2697,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) showCursor(); } } else { - bv_->cut(); + bv_->cut(false); } owner_->showState(); setState(); @@ -2507,21 +2708,22 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) { // Reverse the effect of LFUN_BREAKPARAGRAPH_SKIP. LyXText * lt = bv_->getLyXText(); - + LyXCursor cursor = lt->cursor; - + if (!lt->selection.set()) { - if (cursor.pos() == 0 - && !(cursor.par()->params().spaceTop() + if (cursor.pos() == 0 + && !(cursor.par()->params().spaceTop() == VSpace (VSpace::NONE))) { - lt->setParagraph + lt->setParagraph (bv_, - cursor.par()->params().lineTop(), + cursor.par()->params().lineTop(), cursor.par()->params().lineBottom(), - cursor.par()->params().pagebreakTop(), + cursor.par()->params().pagebreakTop(), cursor.par()->params().pagebreakBottom(), VSpace(VSpace::NONE), cursor.par()->params().spaceBottom(), - cursor.par()->params().align(), + cursor.par()->params().spacing(), + cursor.par()->params().align(), cursor.par()->params().labelWidthString(), 0); update(lt, BufferView::SELECT @@ -2536,14 +2738,14 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::CHANGE); } } else - bv_->cut(); + bv_->cut(false); } break; case LFUN_BREAKPARAGRAPH: { LyXText * lt = bv_->getLyXText(); - + beforeChange(lt); lt->breakParagraph(bv_, 0); update(lt, @@ -2559,7 +2761,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_BREAKPARAGRAPHKEEPLAYOUT: { LyXText * lt = bv_->getLyXText(); - + beforeChange(lt); lt->breakParagraph(bv_, 1); update(lt, @@ -2571,30 +2773,31 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->showState(); 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. LyXText * lt = bv_->getLyXText(); - + LyXCursor cursor = lt->cursor; - + beforeChange(lt); if (cursor.pos() == 0) { if (cursor.par()->params().spaceTop() == VSpace(VSpace::NONE)) { lt->setParagraph (bv_, - cursor.par()->params().lineTop(), + cursor.par()->params().lineTop(), cursor.par()->params().lineBottom(), - cursor.par()->params().pagebreakTop(), + cursor.par()->params().pagebreakTop(), cursor.par()->params().pagebreakBottom(), VSpace(VSpace::DEFSKIP), cursor.par()->params().spaceBottom(), - cursor.par()->params().align(), + cursor.par()->params().spacing(), + cursor.par()->params().align(), cursor.par()->params().labelWidthString(), 1); //update(BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); - } + } } else { lt->breakParagraph(bv_, 0); @@ -2614,14 +2817,14 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_PARAGRAPH_SPACING: { LyXText * lt = bv_->getLyXText(); - + Paragraph * par = lt->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 istr(argument.c_str()); string tmp; @@ -2660,7 +2863,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) } } break; - + case LFUN_INSET_TOGGLE: { LyXText * lt = bv_->getLyXText(); @@ -2670,7 +2873,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) lt->toggleInset(bv_); update(lt, BufferView::SELECT|BufferView::FITCUR); setState(); - } + } break; case LFUN_QUOTE: @@ -2688,7 +2891,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->getDialogs()->createUrl(p.getAsString()); } break; - + case LFUN_INSERT_URL: { InsetCommandParams p; @@ -2701,62 +2904,54 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) updateInset(inset, true); } break; - - case LFUN_INSET_TEXT: - insertAndEditInset(new InsetText); - break; - + case LFUN_INSET_ERT: - insertAndEditInset(new InsetERT); + insertAndEditInset(new InsetERT(buffer_->params)); break; - + case LFUN_INSET_EXTERNAL: insertAndEditInset(new InsetExternal); break; - + case LFUN_INSET_FOOTNOTE: - insertAndEditInset(new InsetFoot); + insertAndEditInset(new InsetFoot(buffer_->params)); break; case LFUN_INSET_MARGINAL: - insertAndEditInset(new InsetMarginal); + insertAndEditInset(new InsetMarginal(buffer_->params)); break; case LFUN_INSET_MINIPAGE: - insertAndEditInset(new InsetMinipage); + insertAndEditInset(new InsetMinipage(buffer_->params)); break; case LFUN_INSERT_NOTE: - insertAndEditInset(new InsetNote); + insertAndEditInset(new InsetNote(buffer_->params)); break; case LFUN_INSET_FLOAT: // check if the float type exist if (floatList.typeExist(argument)) { - insertAndEditInset(new InsetFloat(argument)); + insertAndEditInset(new InsetFloat(buffer_->params, + argument)); } else { - lyxerr << "Non-existant float type: " + lyxerr << "Non-existent float type: " << argument << endl; } break; case LFUN_INSET_WIDE_FLOAT: - { // check if the float type exist if (floatList.typeExist(argument)) { - InsetFloat * new_inset = new InsetFloat(argument); + InsetFloat * new_inset = + new InsetFloat(buffer_->params, argument); new_inset->wide(true); - if (insertInset(new_inset)) - new_inset->edit(bv_); - else - delete new_inset; + insertAndEditInset(new_inset); } else { - lyxerr << "Non-existant float type: " + lyxerr << "Non-existent float type: " << argument << endl; } - - } - break; + break; #if 0 case LFUN_INSET_LIST: @@ -2767,14 +2962,15 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) insertAndEditInset(new InsetTheorem); break; #endif - + case LFUN_INSET_CAPTION: { // Do we have a locking inset... if (bv_->theLockingInset()) { lyxerr << "Locking inset code: " << static_cast(bv_->theLockingInset()->lyxCode()); - InsetCaption * new_inset = new InsetCaption; + InsetCaption * new_inset = + new InsetCaption(buffer_->params); new_inset->setOwner(bv_->theLockingInset()); new_inset->setAutoBreakRows(true); new_inset->setDrawFrame(0, InsetText::LOCKED); @@ -2786,7 +2982,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) } } break; - + case LFUN_INSET_TABULAR: { int r = 2; @@ -2806,7 +3002,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_CHARATCURSOR: { - Paragraph::size_type pos = bv_->getLyXText()->cursor.pos(); + pos_type pos = bv_->getLyXText()->cursor.pos(); if (pos < bv_->getLyXText()->cursor.par()->size()) owner_->getLyXFunc()->setMessage( tostr(bv_->getLyXText()->cursor.par()->getChar(pos))); @@ -2814,13 +3010,13 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->getLyXFunc()->setMessage("EOF"); } break; - + case LFUN_GETXY: owner_->getLyXFunc()->setMessage(tostr(bv_->getLyXText()->cursor.x()) + ' ' + tostr(bv_->getLyXText()->cursor.y())); break; - + case LFUN_SETXY: { int x = 0; @@ -2832,26 +3028,26 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) bv_->getLyXText()->setCursorFromCoordinates(bv_, x, y); } break; - + case LFUN_GETLAYOUT: - owner_->getLyXFunc()->setMessage(tostr(bv_->getLyXText()->cursor.par()->layout)); + owner_->getLyXFunc()->setMessage(tostr(bv_->getLyXText()->cursor.par()->layout())); break; - + case LFUN_GETFONT: { LyXFont & font = bv_->getLyXText()->current_font; - if (font.shape() == LyXFont::ITALIC_SHAPE) + if (font.shape() == LyXFont::ITALIC_SHAPE) owner_->getLyXFunc()->setMessage("E"); - else if (font.shape() == LyXFont::SMALLCAPS_SHAPE) + else if (font.shape() == LyXFont::SMALLCAPS_SHAPE) owner_->getLyXFunc()->setMessage("N"); - else + else owner_->getLyXFunc()->setMessage("0"); } break; // --- accented characters --------------------------- - + case LFUN_UMLAUT: case LFUN_CIRCUMFLEX: case LFUN_GRAVE: @@ -2882,12 +3078,12 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) | BufferView::CHANGE); } break; - + case LFUN_MATH_MACRO: mathDispatchMathMacro(bv_, argument); break; - case LFUN_MATH_DELIM: + case LFUN_MATH_DELIM: mathDispatchMathDelim(bv_, argument); break; @@ -2907,36 +3103,38 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) mathDispatchMathDisplay(bv_, argument); break; - case LFUN_MATH_MODE: // Open or create an inlined math inset + case LFUN_MATH_MODE: // Open or create an inlined math inset mathDispatchMathMode(bv_, argument); break; - + + case LFUN_GREEK: // Insert a single greek letter + mathDispatchGreek(bv_, argument); + break; + case LFUN_CITATION_INSERT: { InsetCommandParams p; - p.setFromString( argument ); + p.setFromString(argument); - InsetCitation * inset = new InsetCitation( p ); + InsetCitation * inset = new InsetCitation(p); if (!insertInset(inset)) delete inset; else - updateInset( inset, true ); + updateInset(inset, true); } break; - + case LFUN_INSERT_BIBTEX: - { + { // ale970405+lasgoutt970425 - // The argument can be up to two tokens separated + // The argument can be up to two tokens separated // by a space. The first one is the bibstyle. string const db = token(argument, ' ', 0); - string bibstyle = token(argument, ' ', 1); - if (bibstyle.empty()) - bibstyle = "plain"; + string const bibstyle = token(argument, ' ', 1); - InsetCommandParams p( "BibTeX", db, bibstyle ); + InsetCommandParams p("BibTeX", db, bibstyle); InsetBibtex * inset = new InsetBibtex(p); - + if (insertInset(inset)) { if (argument.empty()) inset->edit(bv_); @@ -2944,48 +3142,44 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) delete inset; } break; - + // BibTeX data bases case LFUN_BIBDB_ADD: { - InsetBibtex * inset = + InsetBibtex * inset = static_cast(getInsetByCode(Inset::BIBTEX_CODE)); if (inset) { inset->addDatabase(argument); } } break; - + case LFUN_BIBDB_DEL: { - InsetBibtex * inset = + InsetBibtex * inset = static_cast(getInsetByCode(Inset::BIBTEX_CODE)); if (inset) { inset->delDatabase(argument); } } break; - + case LFUN_BIBTEX_STYLE: { - InsetBibtex * inset = + InsetBibtex * inset = static_cast(getInsetByCode(Inset::BIBTEX_CODE)); if (inset) { inset->setOptions(argument); } } break; - + case LFUN_INDEX_CREATE: { InsetCommandParams p("index"); if (argument.empty()) { string const idxstring(bv_->getLyXText()->getStringToIndex(bv_)); - if (!idxstring.empty()) { - p.setContents(idxstring); - } else { - break; - } + p.setContents(idxstring); } else { p.setContents(argument); } @@ -2993,7 +3187,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) owner_->getDialogs()->createIndex(p.getAsString()); } break; - + case LFUN_INDEX_INSERT: { InsetCommandParams p; @@ -3006,7 +3200,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) updateInset(inset, true); } break; - + case LFUN_INDEX_INSERT_LAST: { string const idxstring(bv_->getLyXText()->getStringToIndex(bv_)); @@ -3015,7 +3209,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) + idxstring + _(("' indexed."))); InsetCommandParams p("index", idxstring); InsetIndex * inset = new InsetIndex(p); - + if (!insertInset(inset)) delete inset; else @@ -3028,20 +3222,19 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) { InsetCommandParams p("printindex"); Inset * inset = new InsetPrintIndex(p); - if (!insertInset(inset, "Standard")) + if (!insertInset(inset, tclass.defaultLayoutName())) delete inset; } break; case LFUN_PARENTINSERT: { - lyxerr << "arg " << argument << endl; - InsetCommandParams p( "lyxparent", argument ); + InsetCommandParams p("lyxparent", argument); Inset * inset = new InsetParent(p, *buffer_); - if (!insertInset(inset, "Standard")) + if (!insertInset(inset, tclass.defaultLayoutName())) delete inset; } - + break; case LFUN_CHILD_INSERT: @@ -3058,29 +3251,32 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) bv_->owner()->getDialogs()->showInclude(inset); } } - break; + break; case LFUN_FLOAT_LIST: - { - // We should check the argument for validity. (Lgb) - Inset * inset = new InsetFloatList(argument); - if (!insertInset(inset, "Standard")) - delete inset; - } - break; - + if (floatList.typeExist(argument)) { + Inset * inset = new InsetFloatList(argument); + if (!insertInset(inset, tclass.defaultLayoutName())) + delete inset; + } else { + lyxerr << "Non-existent float type: " + << argument << endl; + } + break; + case LFUN_THESAURUS_ENTRY: { string arg = argument; if (arg.empty()) { - arg = bv_->getLyXText()->selectionAsString(buffer_); - + arg = bv_->getLyXText()->selectionAsString(buffer_, + false); + // FIXME if (arg.size() > 100 || arg.empty()) { // Get word or selection bv_->getLyXText()->selectWordWhenUnderCursor(bv_, LyXText::WHOLE_WORD); - arg = bv_->getLyXText()->selectionAsString(buffer_); + arg = bv_->getLyXText()->selectionAsString(buffer_, false); // FIXME: where is getLyXText()->unselect(bv_) ? } } @@ -3088,11 +3284,11 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) bv_->owner()->getDialogs()->showThesaurus(arg); } break; - + case LFUN_SELFINSERT: { if (argument.empty()) break; - + /* Automatically delete the currently selected * text and replace it with what is being * typed in now. Depends on lyxrc settings @@ -3100,34 +3296,35 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) * true (on). */ LyXText * lt = bv_->getLyXText(); - + if (lyxrc.auto_region_delete) { if (lt->selection.set()) { - lt->cutSelection(bv_, false); + lt->cutSelection(bv_, false, false); bv_->update(lt, BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE); } + workarea_.haveSelection(false); } - + beforeChange(lt); LyXFont const old_font(lt->real_current_font); - + string::const_iterator cit = argument.begin(); string::const_iterator end = argument.end(); for (; cit != end; ++cit) { owner_->getIntl()->getTrans().TranslateAndInsert(*cit, lt); } - + bv_->update(lt, BufferView::SELECT | BufferView::FITCUR | BufferView::CHANGE); - + lt->selection.cursor = lt->cursor; moveCursorUpdate(false); - + // real_current_font.number can change so we need to // update the minibuffer if (old_font != lt->real_current_font) @@ -3144,14 +3341,14 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) string arg; if (!argument.empty()) arg = argument; - else + else arg = lyxrc.date_insert_format; char datetmp[32]; int const datetmp_len = ::strftime(datetmp, 32, arg.c_str(), now_tm); LyXText * lt = bv_->getLyXText(); - + for (int i = 0; i < datetmp_len; i++) { lt->insertChar(bv_, datetmp[i]); update(lt, @@ -3168,7 +3365,7 @@ bool BufferView::Pimpl::Dispatch(kb_action action, string const & argument) case LFUN_UNKNOWN_ACTION: owner_->getLyXFunc()->setErrorMessage(N_("Unknown function!")); break; - + default: return false; } // end of switch @@ -3211,19 +3408,15 @@ void BufferView::Pimpl::hfill() } -void BufferView::Pimpl::protectedBlank(LyXText * lt) +void BufferView::Pimpl::specialChar(InsetSpecialChar::Kind kind) { if (available()) { + LyXText * lt = bv_->getLyXText(); + hideCursor(); update(lt, BufferView::SELECT|BufferView::FITCUR); InsetSpecialChar * new_inset = - new InsetSpecialChar(InsetSpecialChar::PROTECTED_SEPARATOR); -#ifdef WITH_WARNINGS -#warning Why is this code different from specialChar() below? (JMarc) -// the code in specialChar is a generic version of what used to exist -// for other special chars. I did not merge this case because of the -// call to updateInset(), but what does it do? -#endif + new InsetSpecialChar(kind); if (!insertInset(new_inset)) delete new_inset; else @@ -3232,39 +3425,29 @@ void BufferView::Pimpl::protectedBlank(LyXText * lt) } -void BufferView::Pimpl::specialChar(InsetSpecialChar::Kind kind) -{ - if (available()) { - LyXText * lt = bv_->getLyXText(); - - hideCursor(); - update(lt, BufferView::SELECT|BufferView::FITCUR); - InsetSpecialChar * new_inset = - new InsetSpecialChar(kind); - insertInset(new_inset); - } -} - - void BufferView::Pimpl::smartQuote() { + LyXText const * lt = bv_->getLyXText(); + Paragraph const * par = lt->cursor.par(); + pos_type pos = lt->cursor.pos(); char c; - LyXText * lt = bv_->getLyXText(); - if (lt->cursor.pos()) - c = lt->cursor.par()->getChar(lt->cursor.pos() - 1); - else + if (!pos + || (par->isInset(pos - 1) + && par->getInset(pos - 1)->isSpace())) c = ' '; + else + c = par->getChar(pos - 1); + hideCursor(); - LyXLayout const & style = textclasslist.Style( - bv_->buffer()->params.textclass, - lt->cursor.par()->getLayout()); - + LyXLayout const & style = + textclasslist[bv_->buffer()->params.textclass][par->layout()]; + if (style.pass_thru || (!insertInset(new InsetQuotes(c, bv_->buffer()->params)))) - Dispatch(LFUN_SELFINSERT, "\""); + bv_->owner()->getLyXFunc()->dispatch(LFUN_SELFINSERT, "\""); } @@ -3276,12 +3459,12 @@ void BufferView::Pimpl::insertAndEditInset(Inset * inset) delete inset; } - + // Open and lock an updatable inset bool BufferView::Pimpl::open_new_inset(UpdatableInset * new_inset, bool behind) { LyXText * lt = bv_->getLyXText(); - + beforeChange(lt); finishUndo(); if (!insertInset(new_inset)) { @@ -3306,7 +3489,7 @@ bool BufferView::Pimpl::insertInset(Inset * inset, string const & lout) // not quite sure if we want this... setCursorParUndo(bv_); freezeUndo(); - + beforeChange(bv_->text); if (!lout.empty()) { update(bv_->text, BufferView::SELECT|BufferView::FITCUR); @@ -3315,34 +3498,37 @@ bool BufferView::Pimpl::insertInset(Inset * inset, string const & lout) if (bv_->text->cursor.par()->size()) { bv_->text->cursorLeft(bv_); - + bv_->text->breakParagraph(bv_); update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); } - pair lres = - textclasslist.NumberOfLayout(buffer_->params - .textclass, lout); - LyXTextClass::size_type lay; - if (lres.first != false) { + string lres = lout; + LyXTextClass const & tclass = + textclasslist[buffer_->params.textclass]; + bool hasLayout = tclass.hasLayout(lres); + string lay = tclass.defaultLayoutName(); + + if (hasLayout != false) { // layout found - lay = lres.second; + lay = lres; } else { - // layout not fount using default "Standard" (0) - lay = 0; + // layout not fount using default + lay = tclass.defaultLayoutName(); } - + bv_->text->setLayout(bv_, lay); - + bv_->text->setParagraph(bv_, 0, 0, 0, 0, VSpace(VSpace::NONE), VSpace(VSpace::NONE), - LYX_ALIGN_LAYOUT, + Spacing(), + LYX_ALIGN_LAYOUT, string(), 0); update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); } - + bv_->text->insertInset(bv_, inset); update(bv_->text, BufferView::SELECT|BufferView::FITCUR|BufferView::CHANGE); @@ -3353,7 +3539,7 @@ bool BufferView::Pimpl::insertInset(Inset * inset, string const & lout) void BufferView::Pimpl::updateInset(Inset * inset, bool mark_dirty) { - if (!inset) + if (!inset || !available()) return; // first check for locking insets @@ -3368,10 +3554,9 @@ void BufferView::Pimpl::updateInset(Inset * inset, bool mark_dirty) return; } } else if (bv_->theLockingInset()->updateInsetInInset(bv_, inset)) { - if (bv_->text->updateInset(bv_, - bv_->theLockingInset())) { + if (bv_->text->updateInset(bv_, bv_->theLockingInset())) { update(); - if (mark_dirty){ + if (mark_dirty) { buffer_->markDirty(); } updateScrollbar(); @@ -3379,10 +3564,15 @@ void BufferView::Pimpl::updateInset(Inset * inset, bool mark_dirty) } } } - - // then check the current buffer - if (available()) { - hideCursor(); + + // then check if the inset is a top_level inset (has no owner) + // if yes do the update as always otherwise we have to update the + // toplevel inset where this inset is inside + Inset * tl_inset = inset; + while(tl_inset->owner()) + tl_inset = tl_inset->owner(); + hideCursor(); + if (tl_inset == inset) { update(bv_->text, BufferView::UPDATE); if (bv_->text->updateInset(bv_, inset)) { if (mark_dirty) { @@ -3395,6 +3585,13 @@ void BufferView::Pimpl::updateInset(Inset * inset, bool mark_dirty) } return; } + } else if (static_cast(tl_inset) + ->updateInsetInInset(bv_, inset)) + { + if (bv_->text->updateInset(bv_, tl_inset)) { + update(); + updateScrollbar(); + } } } @@ -3403,26 +3600,29 @@ void BufferView::Pimpl::gotoInset(vector const & codes, bool same_content) { if (!available()) return; - + hideCursor(); beforeChange(bv_->text); update(bv_->text, BufferView::SELECT|BufferView::FITCUR); - + + LyXCursor const & cursor = bv_->text->cursor; + string contents; if (same_content && - bv_->text->cursor.par()->getChar(bv_->text->cursor.pos()) == Paragraph::META_INSET) { - Inset const * inset = bv_->text->cursor.par()->getInset(bv_->text->cursor.pos()); + 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 (!bv_->text->gotoNextInset(bv_, codes, contents)) { - if (bv_->text->cursor.pos() - || bv_->text->cursor.par() != bv_->text->firstParagraph()) { + if (bv_->text->cursor.pos() + || bv_->text->cursor.par() != bv_->text->ownerParagraph()) { LyXCursor tmp = bv_->text->cursor; - bv_->text->cursor.par(bv_->text->firstParagraph()); + bv_->text->cursor.par(bv_->text->ownerParagraph()); bv_->text->cursor.pos(0); if (!bv_->text->gotoNextInset(bv_, codes, contents)) { bv_->text->cursor = tmp;