#include "BufferView.h"
+#include "BranchList.h"
#include "Buffer.h"
#include "buffer_funcs.h"
#include "BufferList.h"
#include "insets/InsetGraphics.h"
#include "insets/InsetRef.h"
#include "insets/InsetText.h"
+#include "insets/InsetNote.h"
#include "frontends/alert.h"
#include "frontends/Application.h"
d->cursor_.setCurrentFont();
if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
- graphics::Previews::get().generateBufferPreviews(buffer_);
+ thePreviews().generateBufferPreviews(buffer_);
}
LastFilePosSection::FilePos fp;
fp.pit = d->cursor_.bottom().pit();
fp.pos = d->cursor_.bottom().pos();
- LyX::ref().session().lastFilePos().save(buffer_.fileName(), fp);
+ theSession().lastFilePos().save(buffer_.fileName(), fp);
delete d;
}
void BufferView::updateScrollbar()
{
- if (height_ == 0)
+ if (height_ == 0 && width_ == 0)
return;
// We prefer fixed size line scrolling.
docstring BufferView::contextMenu(int x, int y) const
{
+ //If there is a selection, return the containing inset menu
+ if (d->cursor_.selection())
+ return d->cursor_.inset().contextMenu(*this, x, y);
+
// Get inset under mouse, if there is one.
Inset const * covering_inset = getCoveringInset(buffer_.text(), x, y);
if (covering_inset)
// If the offset is less than 2 screen height, prefer to scroll instead.
if (abs(offset) <= 2 * height_) {
scroll(offset);
+ updateMetrics();
+ buffer_.changed();
return;
}
int const height = 2 * defaultRowHeight();
int const first = height;
int const last = height_ - height;
- Cursor & cur = d->cursor_;
+ int newy = 0;
+ Cursor const & oldcur = d->cursor_;
- switch (cursorStatus(cur)) {
+ switch (cursorStatus(oldcur)) {
case CUR_ABOVE:
- // We reset the cursor because cursorStatus() does not
- // work when the cursor is within mathed.
- cur.reset(buffer_.inset());
- tm.setCursorFromCoordinates(cur, 0, first);
- cur.clearSelection();
+ newy = first;
break;
case CUR_BELOW:
- // We reset the cursor because cursorStatus() does not
- // work when the cursor is within mathed.
- cur.reset(buffer_.inset());
- tm.setCursorFromCoordinates(cur, 0, last);
- cur.clearSelection();
+ newy = last;
break;
case CUR_INSIDE:
- int const y = getPos(cur, cur.boundary()).y_;
- int const newy = min(last, max(y, first));
- if (y != newy) {
- cur.reset(buffer_.inset());
- tm.setCursorFromCoordinates(cur, 0, newy);
- }
+ int const y = getPos(oldcur, oldcur.boundary()).y_;
+ newy = min(last, max(y, first));
+ if (y == newy)
+ return;
}
+ // We reset the cursor because cursorStatus() does not
+ // work when the cursor is within mathed.
+ Cursor cur(*this);
+ cur.reset(buffer_.inset());
+ tm.setCursorFromCoordinates(cur, 0, newy);
+ mouseSetCursor(cur);
}
// acturately locate a bookmark in a 'live' lyx session.
// pit and pos will be updated with bottom level pit/pos
// when lyx exits.
- LyX::ref().session().bookmarks().save(
+ theSession().bookmarks().save(
buffer_.fileName(),
d->cursor_.bottom().pit(),
d->cursor_.bottom().pos(),
int ypos = pm.position() + offset;
Dimension const & row_dim =
pm.getRow(cs.pos(), dit.boundary()).dimension();
+ int scrolled = 0;
if (ypos - row_dim.ascent() < 0)
- scrollUp(- ypos + row_dim.ascent());
+ scrolled = scrollUp(- ypos + row_dim.ascent());
else if (ypos + row_dim.descent() > height_)
- scrollDown(ypos - height_ + row_dim.descent());
+ scrolled = scrollDown(ypos - height_ + row_dim.descent());
// else, nothing to do, the cursor is already visible so we just return.
+ if (scrolled != 0) {
+ updateMetrics();
+ buffer_.changed();
+ }
return;
}
switch (cmd.action) {
case LFUN_UNDO:
- flag.enabled(buffer_.undo().hasUndoStack());
+ flag.setEnabled(buffer_.undo().hasUndoStack());
break;
case LFUN_REDO:
- flag.enabled(buffer_.undo().hasRedoStack());
+ flag.setEnabled(buffer_.undo().hasRedoStack());
break;
case LFUN_FILE_INSERT:
case LFUN_FILE_INSERT_PLAINTEXT_PARA:
case LFUN_FILE_INSERT_PLAINTEXT:
case LFUN_BOOKMARK_SAVE:
// FIXME: Actually, these LFUNS should be moved to Text
- flag.enabled(cur.inTexted());
+ flag.setEnabled(cur.inTexted());
break;
case LFUN_FONT_STATE:
case LFUN_LABEL_INSERT:
case LFUN_SCREEN_RECENTER:
case LFUN_BIBTEX_DATABASE_ADD:
case LFUN_BIBTEX_DATABASE_DEL:
+ case LFUN_GRAPHICS_GROUPS_UNIFY:
+ case LFUN_NOTES_MUTATE:
+ case LFUN_ALL_INSETS_TOGGLE:
case LFUN_STATISTICS:
- flag.enabled(true);
+ flag.setEnabled(true);
break;
case LFUN_NEXT_INSET_TOGGLE:
}
case LFUN_LABEL_GOTO: {
- flag.enabled(!cmd.argument().empty()
+ flag.setEnabled(!cmd.argument().empty()
|| getInsetByCode<InsetRef>(cur, REF_CODE));
break;
}
case LFUN_CHANGES_TRACK:
- flag.enabled(true);
+ flag.setEnabled(true);
flag.setOnOff(buffer_.params().trackChanges);
break;
case LFUN_CHANGES_OUTPUT:
- flag.enabled(true);
+ flag.setEnabled(true);
flag.setOnOff(buffer_.params().outputChanges);
break;
// In principle, these command should only be enabled if there
// is a change in the document. However, without proper
// optimizations, this will inevitably result in poor performance.
- flag.enabled(true);
+ flag.setEnabled(true);
break;
case LFUN_BUFFER_TOGGLE_COMPRESSION: {
case LFUN_SCROLL:
case LFUN_SCREEN_UP_SELECT:
case LFUN_SCREEN_DOWN_SELECT:
- flag.enabled(true);
+ flag.setEnabled(true);
break;
case LFUN_LAYOUT_TABULAR:
- flag.enabled(cur.innerInsetOfType(TABULAR_CODE));
+ flag.setEnabled(cur.innerInsetOfType(TABULAR_CODE));
break;
case LFUN_LAYOUT:
- flag.enabled(!cur.inset().forceEmptyLayout(cur.idx()));
+ flag.setEnabled(!cur.inset().forcePlainLayout(cur.idx()));
break;
case LFUN_LAYOUT_PARAGRAPH:
- flag.enabled(cur.inset().allowParagraphCustomization(cur.idx()));
+ flag.setEnabled(cur.inset().allowParagraphCustomization(cur.idx()));
break;
case LFUN_INSET_SETTINGS: {
InsetCode code = cur.inset().lyxCode();
if (cmd.getArg(0) == insetName(code)) {
- flag.enabled(true);
+ flag.setEnabled(true);
break;
}
bool enable = false;
InsetCode next_code = cur.nextInset()
? cur.nextInset()->lyxCode() : NO_CODE;
+ //FIXME: remove these special cases:
switch (next_code) {
case TABULAR_CODE:
case ERT_CODE:
default:
break;
}
- flag.enabled(enable);
+ flag.setEnabled(enable);
break;
}
case LFUN_DIALOG_SHOW_NEW_INSET:
- flag.enabled(cur.inset().lyxCode() != ERT_CODE &&
+ flag.setEnabled(cur.inset().lyxCode() != ERT_CODE &&
cur.inset().lyxCode() != LISTINGS_CODE);
if (cur.inset().lyxCode() == CAPTION_CODE) {
FuncStatus flag;
}
break;
+ case LFUN_BRANCH_ACTIVATE:
+ case LFUN_BRANCH_DEACTIVATE: {
+ bool enable = false;
+ docstring const branchName = cmd.argument();
+ if (!branchName.empty())
+ enable = buffer_.params().branchlist().find(branchName);
+ flag.setEnabled(enable);
+ break;
+ }
+
default:
- flag.enabled(false);
+ flag.setEnabled(false);
}
return flag;
if (!inset || !cur.result().dispatched())
cur.dispatch(cmd);
+ // FIXME I'm adding the last break to solve a crash,
+ // but that is obviously not right.
if (!cur.result().dispatched())
// It did not work too; no action needed.
break;
+ break;
}
case LFUN_PARAGRAPH_GOTO: {
- int const id = convert<int>(to_utf8(cmd.argument()));
+ int const id = convert<int>(cmd.getArg(0));
+ int const pos = convert<int>(cmd.getArg(1));
int i = 0;
for (Buffer * b = &buffer_; i == 0 || b != &buffer_;
b = theBufferList().next(b)) {
if (b == &buffer_) {
// Set the cursor
+ dit.pos() = pos;
setCursor(dit);
processUpdateFlags(Update::Force | Update::FitCursor);
} else {
buffer_.text().cursorBottom(d->cursor_);
// accept everything in a single step to support atomic undo
buffer_.text().acceptOrRejectChanges(d->cursor_, Text::ACCEPT);
+ // FIXME: Move this LFUN to Buffer so that we don't have to do this:
+ processUpdateFlags(Update::Force | Update::FitCursor);
break;
case LFUN_ALL_CHANGES_REJECT:
// reject everything in a single step to support atomic undo
// Note: reject does not work recursively; the user may have to repeat the operation
buffer_.text().acceptOrRejectChanges(d->cursor_, Text::REJECT);
+ // FIXME: Move this LFUN to Buffer so that we don't have to do this:
+ processUpdateFlags(Update::Force | Update::FitCursor);
break;
case LFUN_WORD_FIND: {
showCursor();
p = getPos(cur, cur.boundary());
}
- scroll(cmd.action == LFUN_SCREEN_UP? - height_ : height_);
+ int const scrolled = scroll(cmd.action == LFUN_SCREEN_UP
+ ? - height_ : height_);
+ if (cmd.action == LFUN_SCREEN_UP && scrolled > - height_)
+ p = Point(0, 0);
+ if (cmd.action == LFUN_SCREEN_DOWN && scrolled < height_)
+ p = Point(width_, height_);
cur.reset(buffer_.inset());
+ updateMetrics();
+ buffer_.changed();
d->text_metrics_[&buffer_.text()].editXY(cur, p.x_, p.y_);
//FIXME: what to do with cur.x_target()?
cur.finishUndo();
break;
}
+ case LFUN_BRANCH_ACTIVATE:
+ case LFUN_BRANCH_DEACTIVATE:
+ buffer_.dispatch(cmd);
+ processUpdateFlags(Update::Force);
+ break;
+
+ // These two could be rewriten using some command like forall <insetname> <command>
+ // once the insets refactoring is done.
+ case LFUN_GRAPHICS_GROUPS_UNIFY: {
+ if (cmd.argument().empty())
+ break;
+ graphics::unifyGraphicsGroups(cur.buffer(), to_utf8(cmd.argument()));
+ processUpdateFlags(Update::Force | Update::FitCursor);
+ break;
+ }
+
+ case LFUN_NOTES_MUTATE: {
+ if (cmd.argument().empty())
+ break;
+
+ if (mutateNotes(cur, cmd.getArg(0), cmd.getArg(1))) {
+ processUpdateFlags(Update::Force);
+ }
+ break;
+ }
+
+ case LFUN_ALL_INSETS_TOGGLE: {
+ string action;
+ string const name = split(to_utf8(cmd.argument()), action, ' ');
+ InsetCode const inset_code = insetCode(name);
+
+ FuncRequest fr(LFUN_INSET_TOGGLE, action);
+
+ Inset & inset = cur.buffer().inset();
+ InsetIterator it = inset_iterator_begin(inset);
+ InsetIterator const end = inset_iterator_end(inset);
+ for (; it != end; ++it) {
+ if (it->asInsetCollapsable()
+ && (inset_code == NO_CODE
+ || inset_code == it->lyxCode())) {
+ Cursor tmpcur = cur;
+ tmpcur.pushBackward(*it);
+ it->dispatch(tmpcur, fr);
+ }
+ }
+ processUpdateFlags(Update::Force | Update::FitCursor);
+ break;
+ }
+
default:
return false;
}
{
Cursor & cur = d->cursor_;
+ LYXERR(Debug::SELECTION, "requestSelection: cur.selection: " << cur.selection());
if (!cur.selection()) {
d->xsel_cache_.set = false;
return docstring();
}
+ LYXERR(Debug::SELECTION, "requestSelection: xsel_cache.set: " << d->xsel_cache_.set);
if (!d->xsel_cache_.set ||
cur.top() != d->xsel_cache_.cursor ||
cur.anchor_.top() != d->xsel_cache_.anchor)
// Put anchor at the same position.
cur.resetAnchor();
+ cur.beginUndoGroup();
+
// Try to dispatch to an non-editable inset near this position
// via the temp cursor. If the inset wishes to change the real
// cursor it has to do so explicitly by using
if (!inset || !cur.result().dispatched())
cur.dispatch(cmd);
+ cur.endUndoGroup();
+
// Notify left insets
if (cur != old) {
old.fixIfBroken();
if (scroll_value)
scroll(scroll_step * scroll_value);
}
+ updateMetrics();
+ buffer_.changed();
}
-void BufferView::scroll(int y)
+int BufferView::scroll(int y)
{
if (y > 0)
- scrollDown(y);
- else if (y < 0)
- scrollUp(-y);
+ return scrollDown(y);
+ if (y < 0)
+ return scrollUp(-y);
+ return 0;
}
-void BufferView::scrollDown(int offset)
+int BufferView::scrollDown(int offset)
{
Text * text = &buffer_.text();
TextMetrics & tm = d->text_metrics_[text];
int bottom_pos = last.second->position() + last.second->descent();
if (last.first + 1 == int(text->paragraphs().size())) {
if (bottom_pos <= height_)
- return;
+ return 0;
offset = min(offset, bottom_pos - height_);
break;
}
tm.newParMetricsDown();
}
d->anchor_ypos_ -= offset;
- updateMetrics();
- buffer_.changed();
+ return -offset;
}
-void BufferView::scrollUp(int offset)
+int BufferView::scrollUp(int offset)
{
Text * text = &buffer_.text();
TextMetrics & tm = d->text_metrics_[text];
int top_pos = first.second->position() - first.second->ascent();
if (first.first == 0) {
if (top_pos >= 0)
- return;
+ return 0;
offset = min(offset, - top_pos);
break;
}
tm.newParMetricsUp();
}
d->anchor_ypos_ += offset;
- updateMetrics();
- buffer_.changed();
+ return offset;
}
}
+bool BufferView::setCursorFromInset(Inset const * inset)
+{
+ // are we already there?
+ if (cursor().nextInset() == inset)
+ return true;
+
+ // Inset is not at cursor position. Find it in the document.
+ Cursor cur(*this);
+ cur.reset(buffer().inset());
+ do
+ cur.forwardInset();
+ while (cur && cur.nextInset() != inset);
+
+ if (cur) {
+ setCursor(cur);
+ return true;
+ }
+ return false;
+}
+
+
void BufferView::gotoLabel(docstring const & label)
{
Toc & toc = buffer().tocBackend().toc("label");
void BufferView::updateMetrics()
{
+ if (height_ == 0 || width_ == 0)
+ return;
+
Text & buftext = buffer_.text();
pit_type const npit = int(buftext.paragraphs().size());
void BufferView::draw(frontend::Painter & pain)
{
+ if (height_ == 0 || width_ == 0)
+ return;
LYXERR(Debug::PAINTING, "\t\t*** START DRAWING ***");
Text & text = buffer_.text();
TextMetrics const & tm = d->text_metrics_[&text];