#include "bufferparams.h"
#include "coordcache.h"
#include "cursor.h"
+#include "CutAndPaste.h"
#include "debug.h"
#include "dispatchresult.h"
#include "factory.h"
BufferView::Pimpl::Pimpl(BufferView & bv, LyXView * owner,
int width, int height)
- : bv_(&bv), owner_(owner), buffer_(0), cursor_timeout(400),
- using_xterm_cursor(false), cursor_(bv) ,
+ : bv_(&bv), owner_(owner), buffer_(0), wh_(0), cursor_timeout(400),
+ using_xterm_cursor(false), cursor_(bv),
anchor_ref_(0), offset_ref_(0)
{
xsel_cache_.set = false;
// Fall through to new load. (Asger)
}
- Buffer * b;
+ Buffer * b = 0;
if (found) {
b = bufferlist.newBuffer(s);
lyxerr[Debug::INFO] << BOOST_CURRENT_FUNCTION
<< "[ b = " << b << "]" << endl;
- if (buffer_)
+ if (buffer_) {
disconnectBuffer();
+ // Save the actual cursor position and anchor inside the
+ // buffer so that it can be restored in case we rechange
+ // to this buffer later on.
+ buffer_->saveCursor(cursor_.selectionBegin(),
+ cursor_.selectionEnd());
+ }
// If we are closing current buffer, switch to the first in
// buffer list.
lyxerr[Debug::INFO] << BOOST_CURRENT_FUNCTION
<< "Buffer addr: " << buffer_ << endl;
connectBuffer(*buffer_);
-
cursor_.push(buffer_->inset());
cursor_.resetAnchor();
buffer_->text().init(bv_);
buffer_->text().setCurrentFont(cursor_);
+ if (buffer_->getCursor().size() > 0 &&
+ buffer_->getAnchor().size() > 0)
+ {
+ cursor_.setCursor(buffer_->getAnchor().asDocIterator(&(buffer_->inset())));
+ cursor_.resetAnchor();
+ cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset())));
+ cursor_.setSelection();
+ }
// Buffer-dependent dialogs should be updated or
// hidden. This should go here because some dialogs (eg ToC)
owner_->updateWindowTitle();
// This is done after the layout combox has been populated
- if (buffer_)
- owner_->setLayout(cursor_.paragraph().layout()->name());
+ if (buffer_) {
+ size_t i = cursor_.depth() - 1;
+ // we know we'll eventually find a paragraph
+ while (true) {
+ CursorSlice const & slice = cursor_[i];
+ if (!slice.inset().inMathed()) {
+ LyXLayout_ptr const layout = slice.paragraph().layout();
+ owner_->setLayout(layout->name());
+ break;
+ }
+ BOOST_ASSERT(i>0);
+ --i;
+ }
+ }
if (buffer_ && lyx::graphics::Previews::status() != LyXRC::PREVIEW_OFF)
lyx::graphics::Previews::get().generateBufferPreviews(*buffer_);
}
LyXText & t = *bv_->text();
- if (anchor_ref_ > int(t.paragraphs().size()) - 1) {
- anchor_ref_ = int(t.paragraphs().size()) - 1;
+ int const parsize = int(t.paragraphs().size() - 1);
+ if (anchor_ref_ > parsize) {
+ anchor_ref_ = parsize;
offset_ref_ = 0;
}
// It would be better to fix the scrollbar to understand
// values in [0..1] and divide everything by wh
- int const wh = workarea().workHeight() / 4;
- int const h = t.getPar(anchor_ref_).height();
- workarea().setScrollbarParams(t.paragraphs().size() * wh, anchor_ref_ * wh + int(offset_ref_ * wh / float(h)), int (wh * defaultRowHeight() / float(h)));
-// workarea().setScrollbarParams(t.paragraphs().size(), anchor_ref_, 1);
+
+ // estimated average paragraph height:
+ if (wh_ == 0)
+ wh_ = workarea().workHeight() / 4;
+ int h = t.getPar(anchor_ref_).height();
+
+ // Normalize anchor/offset (MV):
+ while (offset_ref_ > h && anchor_ref_ < parsize) {
+ anchor_ref_++;
+ offset_ref_ -= h;
+ h = t.getPar(anchor_ref_).height();
+ }
+ // Look at paragraph heights on-screen
+ int sumh = 0;
+ int nh = 0;
+ for (lyx::pit_type pit = anchor_ref_; pit <= parsize; ++pit) {
+ if (sumh > workarea().workHeight())
+ break;
+ int const h2 = t.getPar(pit).height();
+ sumh += h2;
+ nh++;
+ }
+ int const hav = sumh / nh;
+ // More realistic average paragraph height
+ if (hav > wh_)
+ wh_ = hav;
+
+ workarea().setScrollbarParams((parsize + 1) * wh_,
+ anchor_ref_ * wh_ + int(offset_ref_ * wh_ / float(h)),
+ int(wh_ * defaultRowHeight() / float(h)));
}
screen().hideCursor();
- int const wh = workarea().workHeight() / 4;
-
LyXText & t = *bv_->text();
- float const bar = value / float(wh * t.paragraphs().size());
+ float const bar = value / float(wh_ * t.paragraphs().size());
anchor_ref_ = int(bar * t.paragraphs().size());
+ if (anchor_ref_ > int(t.paragraphs().size()) - 1)
+ anchor_ref_ = int(t.paragraphs().size()) - 1;
t.redoParagraph(anchor_ref_);
int const h = t.getPar(anchor_ref_).height();
offset_ref_ = int((bar * t.paragraphs().size() - anchor_ref_) * h);
cur.clearSelection();
break;
case bv_funcs::CUR_INSIDE:
- int const y = bv_funcs::getPos(cur).y_;
+ int const y = bv_funcs::getPos(cur, cur.boundary()).y_;
int const newy = min(last, max(y, first));
if (y != newy) {
cur.reset(buffer_->inset());
LyXFont const font = cursor_.getFont();
int const asc = font_metrics::maxAscent(font);
int const des = font_metrics::maxDescent(font);
- Point const p = bv_funcs::getPos(cursor_);
+ Point const p = bv_funcs::getPos(cursor_, cursor_.boundary());
if (p.y_ - asc >= 0 && p.y_ + des < workarea().workHeight())
return false;
}
}
+bool BufferView::Pimpl::multiParSel()
+{
+ if (!cursor_.selection())
+ return false;
+ bool ret = multiparsel_cache_;
+ multiparsel_cache_ = cursor_.selBegin().pit() != cursor_.selEnd().pit();
+ // Either this, or previous selection spans paragraphs
+ return ret || multiparsel_cache_;
+}
+
+
void BufferView::Pimpl::update(Update::flags flags)
{
lyxerr[Debug::DEBUG]
theCoords.startUpdating();
// First drawing step
- ViewMetricsInfo vi = metrics();
- bool forceupdate(flags & Update::Force);
+ ViewMetricsInfo vi = metrics(flags & Update::SinglePar);
+ bool forceupdate(flags & (Update::Force | Update::SinglePar));
if ((flags & Update::FitCursor) && fitCursor()) {
forceupdate = true;
- vi = metrics(flags & Update::SinglePar);
+ vi = metrics();
+ }
+ if ((flags & Update::MultiParSel) && multiParSel()) {
+ forceupdate = true;
+ vi = metrics();
}
if (forceupdate) {
// Second drawing step
bot.text()->redoParagraph(pit);
Paragraph const & par = bot.text()->paragraphs()[pit];
anchor_ref_ = pit;
- offset_ref_ = bv_funcs::coordOffset(cursor_).y_ + par.ascent()
- - workarea().workHeight() / 2;
+ offset_ref_ = bv_funcs::coordOffset(cursor_, cursor_.boundary()).y_
+ + par.ascent() - workarea().workHeight() / 2;
}
void BufferView::Pimpl::MenuInsertLyXFile(string const & filenm)
{
+ BOOST_ASSERT(cursor_.inTexted());
string filename = filenm;
if (filename.empty()) {
string const disp_fn = MakeDisplayPath(filename);
owner_->message(bformat(_("Inserting document %1$s..."), disp_fn));
- cursor_.clearSelection();
- bv_->getLyXText()->breakParagraph(cursor_);
-
- BOOST_ASSERT(cursor_.inTexted());
+ string res;
+ Buffer buf("", false);
+ buf.error.connect(boost::bind(&BufferView::Pimpl::addError, this, _1));
+ if (::loadLyXFile(&buf, MakeAbsPath(filename))) {
+ lyx::cap::pasteParagraphList(cursor_, buf.paragraphs(),
+ buf.params().textclass);
+ res = _("Document %1$s inserted.");
+ } else
+ res = _("Could not insert document %1$s");
- string const fname = MakeAbsPath(filename);
- bool const res = buffer_->readFile(fname, cursor_.pit());
+ owner_->message(bformat(res, disp_fn));
+ bv_->showErrorList(_("Document insertion"));
resizeCurrentBuffer();
-
- string s = res ? _("Document %1$s inserted.")
- : _("Could not insert document %1$s");
- owner_->message(bformat(s, disp_fn));
}
// We cannot allow undos beyond the freeze point
buffer_->undostack().clear();
} else {
- update();
- bv_->text()->setCursor(cursor_, 0, 0);
-#ifdef WITH_WARNINGS
-#warning changes FIXME
-#endif
- bool const found = lyx::find::findNextChange(bv_);
- if (found) {
+ cursor_.setCursor(doc_iterator_begin(buffer_->inset()));
+ if (lyx::find::findNextChange(bv_)) {
owner_->getDialogs().show("changes");
return;
}
if (cur.result().update())
update(Update::FitCursor | Update::Force);
else
- update();
+ update(Update::FitCursor | Update::MultiParSel);
}
// See workAreaKeyPress
case LFUN_FILE_INSERT:
case LFUN_FILE_INSERT_ASCII_PARA:
case LFUN_FILE_INSERT_ASCII:
+ // FIXME: Actually, these LFUNS should be moved to LyXText
+ flag.enabled(cursor_.inTexted());
+ break;
case LFUN_FONT_STATE:
case LFUN_INSERT_LABEL:
case LFUN_BOOKMARK_SAVE:
}
case LFUN_MERGE_CHANGES:
- owner_->getDialogs().show("changes");
+ if (lyx::find::findNextChange(bv_))
+ owner_->getDialogs().show("changes");
break;
case LFUN_ACCEPT_ALL_CHANGES: {
int pit2 = pit;
size_t const npit = text->paragraphs().size();
- lyxerr[Debug::DEBUG]
- << BOOST_CURRENT_FUNCTION
- << " npit: " << npit
- << " pit1: " << pit1
- << " pit2: " << pit2
- << endl;
-
- // Rebreak anchor par
- text->redoParagraph(pit);
- int y0 = text->getPar(pit1).ascent() - offset_ref_;
+ // Rebreak anchor paragraph. In Single Paragraph mode, rebreak only
+ // the (main text, not inset!) paragraph containing the cursor.
+ // (if this paragraph contains insets etc., rebreaking will
+ // recursively descend)
+ if (!singlepar || pit == cursor_.bottom().pit())
+ text->redoParagraph(pit);
+ int y0 = text->getPar(pit).ascent() - offset_ref_;
- // Redo paragraphs above cursor if necessary
+ // Redo paragraphs above anchor if necessary; again, in Single Par
+ // mode, only if we encounter the (main text) one having the cursor.
int y1 = y0;
- while (!singlepar && y1 > 0 && pit1 > 0) {
+ while (y1 > 0 && pit1 > 0) {
y1 -= text->getPar(pit1).ascent();
--pit1;
- text->redoParagraph(pit1);
+ if (!singlepar || pit1 == cursor_.bottom().pit())
+ text->redoParagraph(pit1);
y1 -= text->getPar(pit1).descent();
}
anchor_ref_ = 0;
}
- // Redo paragraphs below cursor if necessary
+ // Redo paragraphs below the anchor if necessary. Single par mode:
+ // only the one containing the cursor if encountered.
int y2 = y0;
- while (!singlepar && y2 < bv.workHeight() && pit2 < int(npit) - 1) {
+ while (y2 < bv.workHeight() && pit2 < int(npit) - 1) {
y2 += text->getPar(pit2).descent();
++pit2;
- text->redoParagraph(pit2);
+ if (!singlepar || pit2 == cursor_.bottom().pit())
+ text->redoParagraph(pit2);
y2 += text->getPar(pit2).ascent();
}
for (lyx::pit_type pit = pit1; pit <= pit2; ++pit) {
y += text->getPar(pit).ascent();
theCoords.parPos()[text][pit] = Point(0, y);
+ if (singlepar && pit == cursor_.bottom().pit()) {
+ // In Single Paragraph mode, collect here the
+ // y1 and y2 of the (one) paragraph the cursor is in
+ y1 = y - text->getPar(pit).ascent();
+ y2 = y + text->getPar(pit).descent();
+ }
y += text->getPar(pit).descent();
}
+ if (singlepar) {
+ // collect cursor paragraph iter bounds
+ pit1 = cursor_.bottom().pit();
+ pit2 = cursor_.bottom().pit();
+ }
+
lyxerr[Debug::DEBUG]
<< BOOST_CURRENT_FUNCTION
<< " y1: " << y1
<< " y2: " << y2
+ << " pit1: " << pit1
+ << " pit2: " << pit2
+ << " npit: " << npit
+ << " singlepar: " << singlepar
<< endl;
return ViewMetricsInfo(pit1, pit2, y1, y2, singlepar);