using support::addPath;
using support::bformat;
using support::FileFilterList;
+using support::FileName;
using support::fileSearch;
using support::isDirWriteable;
+using support::isFileReadable;
using support::makeDisplayPath;
using support::makeAbsPath;
using support::package;
: width_(0), height_(0), buffer_(0), wh_(0),
cursor_(*this),
multiparsel_cache_(false), anchor_ref_(0), offset_ref_(0),
- intl_(new Intl)
+ intl_(new Intl), last_inset_(0)
{
xsel_cache_.set = false;
intl_->initKeyMapper(lyxrc.use_kbmap);
buffer_->saveCursor(cursor_.selectionBegin(),
cursor_.selectionEnd());
// current buffer is going to be switched-off, save cursor pos
- LyX::ref().session().lastFilePos().save(buffer_->fileName(),
+ LyX::ref().session().lastFilePos().save(FileName(buffer_->fileName()),
boost::tie(cursor_.pit(), cursor_.pos()) );
}
}
}
- // FIXME: in principle, a simple call to updateMetrics(false) should
- // be enough here. But, for unknown reason, it seems that only the line
- // of the cursor is updated in the CoordCache.
if (buffer_)
updateMetrics(false);
}
-bool BufferView::loadLyXFile(string const & filename, bool tolastfiles)
+bool BufferView::loadLyXFile(FileName const & filename, bool tolastfiles)
{
- // Get absolute path of file and add ".lyx"
- // to the filename if necessary
- string s = fileSearch(string(), filename, "lyx");
-
- bool const found = !s.empty();
-
- if (!found)
- s = filename;
-
// File already open?
- if (theBufferList().exists(s)) {
- docstring const file = makeDisplayPath(s, 20);
+ if (theBufferList().exists(filename.absFilename())) {
+ docstring const file = makeDisplayPath(filename.absFilename(), 20);
docstring text = bformat(_("The document %1$s is already "
"loaded.\n\nDo you want to revert "
"to the saved version?"), file);
text, 0, 1, _("&Revert"), _("&Switch to document"));
if (ret != 0) {
- setBuffer(theBufferList().getBuffer(s));
+ setBuffer(theBufferList().getBuffer(filename.absFilename()));
return true;
}
// FIXME: should be LFUN_REVERT
- if (!theBufferList().close(theBufferList().getBuffer(s), false))
+ if (!theBufferList().close(theBufferList().getBuffer(filename.absFilename()), false))
return false;
// Fall through to new load. (Asger)
buffer_ = 0;
Buffer * b = 0;
- if (found) {
- b = theBufferList().newBuffer(s);
- if (!lyx::loadLyXFile(b, s)) {
+ if (isFileReadable(filename)) {
+ b = theBufferList().newBuffer(filename.absFilename());
+ if (!lyx::loadLyXFile(b, filename)) {
theBufferList().release(b);
return false;
}
} else {
docstring text = bformat(_("The document %1$s does not yet "
"exist.\n\nDo you want to create "
- "a new document?"), from_utf8(s));
+ "a new document?"), from_utf8(filename.absFilename()));
int const ret = Alert::prompt(_("Create new document?"),
text, 0, 1, _("&Create"), _("Cancel"));
if (ret == 0) {
- b = newFile(s, string(), true);
+ b = newFile(filename.absFilename(), string(), true);
if (!b)
return false;
} else
if (lyxrc.use_lastfilepos) {
pit_type pit;
pos_type pos;
- boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(s);
+ boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(filename);
// I am not sure how to separate the following part to a function
// so I will leave this to Lars.
//
if (it.pit() == pit) {
// restored pos may be bigger than it->size
setCursor(makeDocIterator(it, min(pos, it->size())));
- update(Update::FitCursor);
+ // No need to update the metrics if fitCursor returns false.
+ if (fitCursor())
+ updateMetrics(false);
break;
}
}
}
if (tolastfiles)
- LyX::ref().session().lastFiles().add(b->fileName());
+ LyX::ref().session().lastFiles().add(FileName(b->fileName()));
return true;
}
void BufferView::reload()
{
- string const fn = buffer_->fileName();
if (theBufferList().close(buffer_, false))
- loadLyXFile(fn);
+ loadLyXFile(FileName(buffer_->fileName()));
}
lyxerr[Debug::DEBUG] << BOOST_CURRENT_FUNCTION << endl;
buffer_->text().init(this);
- update();
+ updateMetrics(false);
switchKeyMap();
}
}
-std::pair<bool, bool> BufferView::update(Update::flags flags)
+bool BufferView::update(Update::flags flags)
{
// This is close to a hot-path.
if (lyxerr.debugging(Debug::DEBUG)) {
// Check needed to survive LyX startup
if (!buffer_)
- return make_pair(false, false);
+ return false;
if (lyxerr.debugging(Debug::WORKAREA)) {
lyxerr[Debug::WORKAREA] << "BufferView::update" << std::endl;
// Case when no explicit update is requested.
if (!flags) {
- // no need to do anything.
- return make_pair(false, false);
+ // no need to redraw anything.
+ return false;
+ }
+
+ if (flags == Update::FitCursor) {
+ bool const fit_cursor = fitCursor();
+ if (fit_cursor)
+ updateMetrics(false);
+ // tell the frontend to update the screen if needed.
+ return fit_cursor;
}
bool full_metrics = flags & Update::Force;
updateMetrics(false);
// tell the frontend to update the screen.
- return make_pair(true, single_par);
+ return true;
}
void BufferView::saveBookmark(bool persistent)
{
LyX::ref().session().bookmarks().save(
- buffer_->fileName(),
+ FileName(buffer_->fileName()),
cursor_.paragraph().id(),
cursor_.pos(),
persistent
case LFUN_CHANGE_NEXT:
case LFUN_ALL_CHANGES_ACCEPT:
case LFUN_ALL_CHANGES_REJECT:
- flag.enabled(buffer_); // FIXME: Change tracking (MG)
+ // TODO: context-sensitive enabling of LFUNs
+ // 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(buffer_);
break;
case LFUN_BUFFER_TOGGLE_COMPRESSION: {
break;
case LFUN_FILE_INSERT:
- // FIXME: We don't know the encoding of filenames
+ // FIXME UNICODE
menuInsertLyXFile(to_utf8(cmd.argument()));
break;
case LFUN_FILE_INSERT_ASCII_PARA:
- // FIXME: We don't know the encoding of filenames
+ // FIXME UNICODE
insertAsciiFile(this, to_utf8(cmd.argument()), true);
break;
case LFUN_FILE_INSERT_ASCII:
- // FIXME: We don't know the encoding of filenames
+ // FIXME UNICODE
insertAsciiFile(this, to_utf8(cmd.argument()), false);
break;
void BufferView::workAreaResize(int width, int height)
{
- bool const widthChange = width != width_;
- bool const heightChange = height != height_;
-
+ // A resize is triggered whenever a window gets focus,
+ // because of the shared rows() of a buffer in multiple
+ // buffer views.
+
// Update from work area
width_ = width;
height_ = height;
if (buffer_)
resize();
-
- update();
}
-std::pair<bool, bool> BufferView::workAreaDispatch(FuncRequest const & cmd0)
+bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
{
//lyxerr << BOOST_CURRENT_FUNCTION << "[ cmd0 " << cmd0 << "]" << endl;
// E.g. Qt mouse press when no buffer
if (!buffer_)
- return make_pair(false, false);
+ return false;
LCursor cur(*this);
cur.push(buffer_->inset());
//lyxerr << BOOST_CURRENT_FUNCTION
// << " * created temp cursor:" << cur << endl;
+ // NOTE: editXY returns the top level inset of nested insets. If you happen
+ // to move from a text (inset=0) to a text inside an inset (e.g. an opened
+ // footnote inset, again inset=0), that inset will not be redrawn.
+ if (cmd.action == LFUN_MOUSE_MOTION && cmd.button() == mouse_button::none) {
+ bool need_redraw = false;
+
+ if (inset != last_inset_) {
+ if (last_inset_)
+ need_redraw |= last_inset_->setMouseHover(false);
+ if (inset)
+ need_redraw |= inset->setMouseHover(true);
+ last_inset_ = inset;
+ }
+
+ // if last metrics update was in singlepar mode, WorkArea::redraw() will
+ // not expose the button for redraw. We adjust here the metrics dimension
+ // to enable a full redraw.
+ // FIXME: It is possible to redraw only the area around the button!
+ if (need_redraw && metrics_info_.singlepar) {
+ // FIXME: It should be possible to redraw only the area around
+ // the button by doing this:
+ //
+ //metrics_info_.singlepar = false;
+ //metrics_info_.y1 = ymin of button;
+ //metrics_info_.y2 = ymax of button;
+ //
+ // Unfortunately, rowpainter.C:paintText() does not distinguish
+ // between background updates and text updates. So we use the hammer
+ // solution for now. We could also avoid the updateMetrics() below
+ // by using the first and last pit of the CoordCache. Have a look
+ // at LyXText::getPitNearY() to see what I mean.
+ //
+ //metrics_info_.pit1 = first pit of CoordCache;
+ //metrics_info_.pit2 = last pit of CoordCache;
+ //metrics_info_.singlepar = false;
+ //metrics_info_.y1 = 0;
+ //metrics_info_.y2 = height_;
+ //
+ updateMetrics(false);
+ }
+
+ // This event (moving without mouse click) is not passed further.
+ // This should be changed if it is further utilized.
+ return need_redraw;
+ }
+
// Put anchor at the same position.
cur.resetAnchor();
if (cur.result().dispatched() && cur.result().update())
return update(cur.result().update());
- // When the above and the inner function are fixed, we can do this:
- return make_pair(false, false);
+ return false;
}
}
-void BufferView::mouseSetCursor(LCursor & cur)
+bool BufferView::mouseSetCursor(LCursor & cur)
{
BOOST_ASSERT(&cur.bv() == this);
// do the dEPM magic if needed
// FIXME: move this to InsetText::notifyCursorLeaves?
+ bool update = false;
if (!badcursor && cursor_.inTexted())
- cursor_.text()->deleteEmptyParagraphMechanism(cur, cursor_);
+ update = cursor_.text()->deleteEmptyParagraphMechanism(cur, cursor_);
cursor_ = cur;
cursor_.clearSelection();
cursor_.setTargetX();
finishUndo();
-
+ return update;
}
// Get absolute path of file and add ".lyx"
// to the filename if necessary
- filename = fileSearch(string(), filename, "lyx");
+ filename = fileSearch(string(), filename, "lyx").absFilename();
docstring const disp_fn = makeDisplayPath(filename);
// emit message signal.
docstring res;
Buffer buf("", false);
- if (lyx::loadLyXFile(&buf, makeAbsPath(filename))) {
+ if (lyx::loadLyXFile(&buf, FileName(filename))) {
ErrorList & el = buffer_->errorList("Parse");
// Copy the inserted document error list into the current buffer one.
el = buf.errorList("Parse");