[LyX/master] When catching exception, give error on STDERR

2017-03-10 Thread Scott Kostyshak
commit 3db74fa92d9acd784b271b01c473f69c36311777
Author: Scott Kostyshak 
Date:   Fri Mar 10 17:11:58 2017 -0500

When catching exception, give error on STDERR

The error is reported in the GUI, but for the terminal we must write
explicitly to STDERR.

For a specific example of this type of exception, see the previous
commit, 72c3dbd.
---
 src/Buffer.cpp |1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index b220ee3..84b5e6c 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -1741,6 +1741,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
catch (exception const & e) {
errorList.push_back(ErrorItem(_("conversion failed"),
  _(e.what(;
+   lyxerr << e.what() << endl;
failed_export = true;
}
catch (...) {


[LyX/master] Change a warning to an error if missing include

2017-03-10 Thread Scott Kostyshak
commit 72c3dbd02ccd0a3b85f1c9b940462ac1e7ed98d6
Author: Scott Kostyshak 
Date:   Fri Mar 10 15:38:27 2017 -0500

Change a warning to an error if missing include

If an included file is not found, it seems impossible that the final
output would be correct. Before this commit, when exporting on the
command line, LyX would create the PDF and exit with a zero error
code so unless the user was monitoring the terminal output, they
would not know there is a problem.

This change is consistent with 1a374a93.
---
 src/insets/InsetInclude.cpp |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp
index a5ed017..4820301 100644
--- a/src/insets/InsetInclude.cpp
+++ b/src/insets/InsetInclude.cpp
@@ -640,7 +640,8 @@ void InsetInclude::latex(otexstream & os, OutputParams 
const & runparams) const
"file\n`%1$s'\n"
"Please, check whether it actually 
exists."),
included_file.displayName());
-   Alert::warning(_("Missing included file"), 
text);
+   throw ExceptionMessage(ErrorException, 
_("Error: "),
+  text);
}
return;
}


[LyX/master] Preventive fix inspired from ~

2017-03-10 Thread Guillaume Munch
commit 22edb3df96e78cf10aa94e0f2d9f6f6697534786
Author: Guillaume Munch 
Date:   Fri Mar 10 23:20:29 2017 +0100

Preventive fix inspired from ~
---
 src/TextMetrics.cpp |   27 ---
 1 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/src/TextMetrics.cpp b/src/TextMetrics.cpp
index 5873a28..3dd0520 100644
--- a/src/TextMetrics.cpp
+++ b/src/TextMetrics.cpp
@@ -1361,18 +1361,23 @@ Inset * TextMetrics::editXY(Cursor & cur, int x, int y,
if (edited == inset && cur.pos() == it->pos) {
// non-editable inset, set cursor after the inset if x is
// nearer to that position (bug 9628)
+   // TODO: This should be replaced with an improvement of
+   // Cursor::moveToClosestEdge that handles rtl text. (Which 
could not
+   // be tested because of #10569.)
CoordCache::Insets const & insetCache = 
bv_->coordCache().getInsets();
-   Dimension const & dim = insetCache.dim(inset);
-   Point p = insetCache.xy(inset);
-   bool const is_rtl = text_->isRTL(text_->getPar(pit));
-   if (is_rtl) {
-   // "in front of" == "right of"
-   if (abs(p.x_ - x) < abs(p.x_ + dim.wid - x))
-   cur.posForward();
-   } else {
-   // "in front of" == "left of"
-   if (abs(p.x_ + dim.wid - x) < abs(p.x_ - x))
-   cur.posForward();
+   if (insetCache.has(inset)) {
+   Dimension const & dim = insetCache.dim(inset);
+   Point p = insetCache.xy(inset);
+   bool const is_rtl = text_->isRTL(text_->getPar(pit));
+   if (is_rtl) {
+   // "in front of" == "right of"
+   if (abs(p.x_ - x) < abs(p.x_ + dim.wid - x))
+   cur.posForward();
+   } else {
+   // "in front of" == "left of"
+   if (abs(p.x_ + dim.wid - x) < abs(p.x_ - x))
+   cur.posForward();
+   }
}
}
 


[LyX/master] Replace FileMonitor with FileMonitor2 in RenderPreview

2017-03-10 Thread Guillaume Munch
commit a4fae021f23aa38382673d014cea839aaa9cb812
Author: Guillaume Munch 
Date:   Thu Mar 9 22:44:07 2017 +0100

Replace FileMonitor with FileMonitor2 in RenderPreview
---
 src/insets/InsetExternal.cpp |   10 +++-
 src/insets/InsetInclude.cpp  |8 +++---
 src/insets/RenderPreview.cpp |   44 +++--
 src/insets/RenderPreview.h   |   21 ---
 4 files changed, 58 insertions(+), 25 deletions(-)

diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp
index 8ddd756..3b79249 100644
--- a/src/insets/InsetExternal.cpp
+++ b/src/insets/InsetExternal.cpp
@@ -629,14 +629,12 @@ void InsetExternal::setParams(InsetExternalParams const & 
p)
LASSERT(false, return);
break;
case PREVIEW_INSTANT: {
-   renderer_.reset(new RenderMonitoredPreview(this));
+   renderer_ = make_unique(this);
RenderMonitoredPreview * preview_ptr = 
renderer_->asMonitoredPreview();
-   preview_ptr->fileChanged(bind(&InsetExternal::fileChanged, 
this));
-   if (preview_ptr->monitoring())
-   preview_ptr->stopMonitoring();
+   preview_ptr->connect([=]() { fileChanged(); });
add_preview_and_start_loading(*preview_ptr, *this, buffer());
break;
-   } 
+   }
case PREVIEW_GRAPHICS: {
RenderGraphic * graphic_ptr = renderer_->asGraphic();
if (!graphic_ptr) {
@@ -837,7 +835,7 @@ void InsetExternal::validate(LaTeXFeatures & features) const
 
 
 void InsetExternal::addPreview(DocIterator const & /*inset_pos*/,
-   graphics::PreviewLoader & ploader) const
+   graphics::PreviewLoader & ploader) const
 {
RenderMonitoredPreview * const ptr = renderer_->asMonitoredPreview();
if (!ptr)
diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp
index 3a8c0b8..a5ed017 100644
--- a/src/insets/InsetInclude.cpp
+++ b/src/insets/InsetInclude.cpp
@@ -170,10 +170,10 @@ InsetLabel * createLabel(Buffer * buf, docstring const & 
label_str)
 
 InsetInclude::InsetInclude(Buffer * buf, InsetCommandParams const & p)
: InsetCommand(buf, p), include_label(uniqueID()),
- preview_(new RenderMonitoredPreview(this)), failedtoload_(false),
+ preview_(make_unique(this)), 
failedtoload_(false),
  set_label_(false), label_(0), child_buffer_(0)
 {
-   preview_->fileChanged(bind(&InsetInclude::fileChanged, this));
+   preview_->connect([=](){ fileChanged(); });
 
if (isListings(params())) {
InsetListingsParams listing_params(to_utf8(p["lstparams"]));
@@ -185,10 +185,10 @@ InsetInclude::InsetInclude(Buffer * buf, 
InsetCommandParams const & p)
 
 InsetInclude::InsetInclude(InsetInclude const & other)
: InsetCommand(other), include_label(other.include_label),
- preview_(new RenderMonitoredPreview(this)), failedtoload_(false),
+ preview_(make_unique(this)), 
failedtoload_(false),
  set_label_(false), label_(0), child_buffer_(0)
 {
-   preview_->fileChanged(bind(&InsetInclude::fileChanged, this));
+   preview_->connect([=](){ fileChanged(); });
 
if (other.label_)
label_ = new InsetLabel(*other.label_);
diff --git a/src/insets/RenderPreview.cpp b/src/insets/RenderPreview.cpp
index e985d29..99abca9 100644
--- a/src/insets/RenderPreview.cpp
+++ b/src/insets/RenderPreview.cpp
@@ -271,28 +271,58 @@ void RenderPreview::imageReady(graphics::PreviewImage 
const & pimage)
 
 
 RenderMonitoredPreview::RenderMonitoredPreview(Inset const * inset)
-   : RenderPreview(inset), monitor_(FileName(), 2000)
-{}
+   : RenderPreview(inset)
+{
+   setAbsFile(FileName());
+}
 
 
 void RenderMonitoredPreview::setAbsFile(FileName const & file)
 {
-   monitor_.reset(file);
+   bool mon = monitoring();
+   if (mon)
+   stopMonitoring();
+   filename_ = file;
+   if (mon)
+   startMonitoring();
 }
 
 
 void RenderMonitoredPreview::draw(PainterInfo & pi, int x, int y) const
 {
RenderPreview::draw(pi, x, y);
-   if (!monitoring())
-   startMonitoring();
+   startMonitoring();
 }
 
 
 boost::signals2::connection
-RenderMonitoredPreview::fileChanged(slot_type const & slot)
+RenderMonitoredPreview::connect(ChangedSig::slot_type const & slot)
 {
-   return monitor_.connect(slot);
+   return changed_.connect(slot);
 }
 
+
+bool RenderMonitoredPreview::monitoring() const
+{
+   return (bool) monitor_;
+}
+
+
+void RenderMonitoredPreview::startMonitoring() const
+{
+   if (!monitoring()) {
+   monitor_ = FileSystemWatcher::monitor(filename_);
+   monitor_->connect(changed_);
+   }
+}
+
+
+void RenderMonitoredPreview::stopMonitoring() const
+{
+   monitor_ = nullptr;
+}
+
+
+
+
 } // namespace lyx
diff --git a/src/insets/Re

[LyX/master] Display externally modified status

2017-03-10 Thread Guillaume Munch
commit 1e57fd12b18f82b4fbc00ee5dbe78d03143b4adb
Author: Guillaume Munch 
Date:   Tue Feb 28 22:58:44 2017 +0100

Display externally modified status
---
 src/frontends/WorkAreaManager.cpp   |   13 +
 src/frontends/WorkAreaManager.h |3 ++-
 src/frontends/qt4/GuiView.cpp   |6 ++
 src/frontends/qt4/GuiWorkArea.cpp   |   17 +
 src/frontends/qt4/GuiWorkArea_Private.h |2 ++
 src/frontends/qt4/Menus.cpp |4 
 6 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/src/frontends/WorkAreaManager.cpp 
b/src/frontends/WorkAreaManager.cpp
index f938db4..a1c244e 100644
--- a/src/frontends/WorkAreaManager.cpp
+++ b/src/frontends/WorkAreaManager.cpp
@@ -33,10 +33,8 @@ void WorkAreaManager::remove(WorkArea * wa)
 
 void WorkAreaManager::redrawAll(bool update_metrics)
 {
-   iterator it = work_areas_.begin();
-   iterator const en = work_areas_.end();
-   for (; it != en; ++it)
-   (*it)->redraw(update_metrics);
+   for (WorkArea * wa : work_areas_)
+   wa->redraw(update_metrics);
 }
 
 
@@ -50,12 +48,11 @@ void WorkAreaManager::closeAll()
 
 void WorkAreaManager::updateTitles()
 {
-   iterator it = work_areas_.begin();
-   iterator const en = work_areas_.end();
-   for (; it != en; ++it)
-   (*it)->updateWindowTitle();
+   for (WorkArea * wa : work_areas_)
+   wa->updateWindowTitle();
 }
 
+
 } // namespace frontend
 } // namespace lyx
 
diff --git a/src/frontends/WorkAreaManager.h b/src/frontends/WorkAreaManager.h
index dfef00e..e8952f2 100644
--- a/src/frontends/WorkAreaManager.h
+++ b/src/frontends/WorkAreaManager.h
@@ -38,7 +38,8 @@ public:
void redrawAll(bool update_metrics);
///
void closeAll();
-   /// Update window titles of all users.
+   /// Update window titles of all users and the external modifications
+   /// warning.
void updateTitles();
 
 private:
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index c595632..7ff8e04 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -1121,6 +1121,12 @@ void GuiView::updateWindowTitle(GuiWorkArea * wa)
Buffer const & buf = wa->bufferView().buffer();
// Set the windows title
docstring title = buf.fileName().displayName(130) + from_ascii("[*]");
+   if (buf.notifiesExternalModification()) {
+   title = bformat(_("%1$s (modified externally)"), title);
+   // If the external modification status has changed, then maybe 
the status of
+   // buffer-save has changed too.
+   updateToolbars();
+   }
 #ifndef Q_WS_MAC
title += from_ascii(" - LyX");
 #endif
diff --git a/src/frontends/qt4/GuiWorkArea.cpp 
b/src/frontends/qt4/GuiWorkArea.cpp
index bb8de83..050eae7 100644
--- a/src/frontends/qt4/GuiWorkArea.cpp
+++ b/src/frontends/qt4/GuiWorkArea.cpp
@@ -251,7 +251,7 @@ GuiWorkArea::Private::Private(GuiWorkArea * parent)
   need_resize_(false), schedule_redraw_(false), preedit_lines_(1),
   pixel_ratio_(1.0),
   completer_(new GuiCompleter(p, p)), dialog_mode_(false),
-  read_only_(false), clean_(true)
+  read_only_(false), clean_(true), externally_modified_(false)
 {
 }
 
@@ -1390,12 +1390,16 @@ QVariant 
GuiWorkArea::inputMethodQuery(Qt::InputMethodQuery query) const
 void GuiWorkArea::updateWindowTitle()
 {
Buffer const & buf = bufferView().buffer();
-   if (buf.fileName() != d->file_name_ || buf.isReadonly() != d->read_only_
-   || buf.lyxvc().vcstatus() != d->vc_status_ || buf.isClean() != 
d->clean_) {
+   if (buf.fileName() != d->file_name_
+   || buf.isReadonly() != d->read_only_
+   || buf.lyxvc().vcstatus() != d->vc_status_
+   || buf.isClean() != d->clean_
+   || buf.notifiesExternalModification() != d->externally_modified_) {
d->file_name_ = buf.fileName();
d->read_only_ = buf.isReadonly();
d->vc_status_ = buf.lyxvc().vcstatus();
d->clean_ = buf.isClean();
+   d->externally_modified_ = buf.notifiesExternalModification();
Q_EMIT titleChanged(this);
}
 }
@@ -2052,9 +2056,14 @@ void TabWorkArea::updateTabTexts()
QString tab_tooltip = it->abs();
if (buf.isReadonly()) {
setTabIcon(tab_index, QIcon(getPixmap("images/", 
"emblem-readonly", "svgz,png")));
-   tab_tooltip = qt_("%1 (read only)").arg(it->abs());
+   tab_tooltip = qt_("%1 (read only)").arg(tab_tooltip);
} else
setTabIcon(tab_index, QIcon());
+   if (buf.notifiesExternalModification()) {
+   QString const warn = qt_("%1 (modified externally)");
+   tab_tooltip = warn.arg(tab_tooltip);
+   tab_text +

[LyX/master] Notification of external modification inspired by gedit

2017-03-10 Thread Guillaume Munch
commit b6b56d85189966dd18223dcc30b3cef1ec6ed39a
Author: Guillaume Munch 
Date:   Thu Mar 2 00:41:02 2017 +0100

Notification of external modification inspired by gedit
---
 src/frontends/qt4/GuiView.cpp  |8 ++--
 src/frontends/qt4/GuiWorkArea.cpp  |   98 +++---
 src/frontends/qt4/GuiWorkArea.h|   29 ++
 src/frontends/qt4/Makefile.am  |1 +
 src/frontends/qt4/ui/WorkAreaUi.ui |  103 
 5 files changed, 226 insertions(+), 13 deletions(-)

diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index e2e6555..d990d79 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -1352,13 +1352,13 @@ double GuiView::pixelRatio() const
return 1.0;
 #endif
 }
-   
-   
+
+
 GuiWorkArea * GuiView::workArea(int index)
 {
if (TabWorkArea * twa = d.currentTabWorkArea())
if (index < twa->count())
-   return dynamic_cast(twa->widget(index));
+   return twa->workArea(index);
return 0;
 }
 
@@ -2767,7 +2767,7 @@ void GuiView::writeSession() const {
for (int i = 0; i < d.splitter_->count(); ++i) {
TabWorkArea * twa = d.tabWorkArea(i);
for (int j = 0; j < twa->count(); ++j) {
-   GuiWorkArea * wa = static_cast(twa->widget(j));
+   GuiWorkArea * wa = twa->workArea(j);
Buffer & buf = wa->bufferView().buffer();
theSession().lastOpened().add(buf.fileName(), wa == 
active_wa);
}
diff --git a/src/frontends/qt4/GuiWorkArea.cpp 
b/src/frontends/qt4/GuiWorkArea.cpp
index 050eae7..dc6ee32 100644
--- a/src/frontends/qt4/GuiWorkArea.cpp
+++ b/src/frontends/qt4/GuiWorkArea.cpp
@@ -1688,15 +1688,24 @@ GuiWorkArea * TabWorkArea::currentWorkArea()
if (count() == 0)
return 0;
 
-   GuiWorkArea * wa = dynamic_cast(currentWidget());
+   GuiWorkAreaContainer * wac =
+   dynamic_cast(currentWidget());
+   LATTEST(wac);
+   GuiWorkArea * wa = wac->workArea();
LATTEST(wa);
return wa;
 }
 
 
+GuiWorkArea const * TabWorkArea::workArea(int index) const
+{
+   return (dynamic_cast(widget(index)))->workArea();
+}
+
+
 GuiWorkArea * TabWorkArea::workArea(int index)
 {
-   return dynamic_cast(widget(index));
+   return (dynamic_cast(widget(index)))->workArea();
 }
 
 
@@ -1717,18 +1726,27 @@ GuiWorkArea * TabWorkArea::workArea(Buffer & buffer)
 void TabWorkArea::closeAll()
 {
while (count()) {
-   GuiWorkArea * wa = workArea(0);
-   LASSERT(wa, return);
+   QWidget * wac = widget(0);
+   LASSERT(wac, return);
removeTab(0);
-   delete wa;
+   delete wac;
}
 }
 
 
+int TabWorkArea::indexOfWorkArea(GuiWorkArea * w) const
+{
+   for (int index = 0; index < count(); ++index)
+   if (workArea(index) == w)
+   return index;
+   return -1;
+}
+
+
 bool TabWorkArea::setCurrentWorkArea(GuiWorkArea * work_area)
 {
LASSERT(work_area, return false);
-   int index = indexOf(work_area);
+   int index = indexOfWorkArea(work_area);
if (index == -1)
return false;
 
@@ -1747,12 +1765,13 @@ bool TabWorkArea::setCurrentWorkArea(GuiWorkArea * 
work_area)
 GuiWorkArea * TabWorkArea::addWorkArea(Buffer & buffer, GuiView & view)
 {
GuiWorkArea * wa = new GuiWorkArea(buffer, view);
+   GuiWorkAreaContainer * wac = new GuiWorkAreaContainer(wa);
wa->setUpdatesEnabled(false);
// Hide tabbar if there's no tab (avoid a resize and a flashing tabbar
// when hiding it again below).
if (!(currentWorkArea() && currentWorkArea()->isFullScreen()))
showBar(count() > 0);
-   addTab(wa, wa->windowTitle());
+   addTab(wac, wa->windowTitle());
QObject::connect(wa, SIGNAL(titleChanged(GuiWorkArea *)),
this, SLOT(updateTabTexts()));
if (currentWorkArea() && currentWorkArea()->isFullScreen())
@@ -1770,13 +1789,14 @@ GuiWorkArea * TabWorkArea::addWorkArea(Buffer & buffer, 
GuiView & view)
 bool TabWorkArea::removeWorkArea(GuiWorkArea * work_area)
 {
LASSERT(work_area, return false);
-   int index = indexOf(work_area);
+   int index = indexOfWorkArea(work_area);
if (index == -1)
return false;
 
work_area->setUpdatesEnabled(false);
+   QWidget * wac = widget(index);
removeTab(index);
-   delete work_area;
+   delete wac;
 
if (count()) {
// make sure the next work area is enabled.
@@ -2180,6 +2200,66 @@ void DragTabBar::dropEvent(QDropEvent * event)
 }
 
 
+GuiWorkAreaContainer::GuiWorkAreaContainer(GuiWorkArea * wa, QWidget * parent)
+   : QWidget(parent), wa_(wa)
+{
+   LASSERT(wa, ret

[LyX/master] Implement real-time detection of external modifications

2017-03-10 Thread Guillaume Munch
commit cf3c035266486b797e4bc3fe1a9e95c87f45f66d
Author: Guillaume Munch 
Date:   Sun Mar 5 20:12:07 2017 +0100

Implement real-time detection of external modifications
---
 src/Buffer.cpp|   69 
 src/Buffer.h  |   29 +
 src/frontends/qt4/GuiView.cpp |7 +---
 3 files changed, 73 insertions(+), 32 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 6b41213..2bc454b 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -91,6 +91,7 @@
 #include "support/debug.h"
 #include "support/docstring_list.h"
 #include "support/ExceptionMessage.h"
+#include "support/FileMonitor.h"
 #include "support/FileName.h"
 #include "support/FileNameList.h"
 #include "support/filetools.h"
@@ -376,6 +377,18 @@ public:
// display the review toolbar, for instance)
mutable bool tracked_changes_present_;
 
+   // Make sure the file monitor monitors the good file.
+   void refreshFileMonitor();
+
+   /// has it been notified of an external modification?
+   bool isExternallyModified() const { return externally_modified_; }
+
+   /// Notify or clear of external modification
+   void fileExternallyModified(bool modified) const;
+
+   /// Block notifications of external modifications
+   FileMonitorBlocker blockFileMonitor() { return 
file_monitor_->block(10); }
+
 private:
/// So we can force access via the accessors.
mutable Buffer const * parent_buffer;
@@ -384,6 +397,10 @@ private:
int char_count_;
int blank_count_;
 
+   /// has been externally modified? Can be reset by the user.
+   mutable bool externally_modified_;
+
+   FileMonitorPtr file_monitor_;
 };
 
 
@@ -425,8 +442,10 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, 
bool readonly_,
  inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
  clone_list_(0), doing_export(false),
  tracked_changes_present_(0), parent_buffer(0),
- word_count_(0), char_count_(0), blank_count_(0)
+ word_count_(0), char_count_(0), blank_count_(0),
+ externally_modified_(false)
 {
+   refreshFileMonitor();
if (!cloned_buffer_) {
temppath = createBufferTmpDir();
lyxvc.setBuffer(owner_);
@@ -864,6 +883,7 @@ void Buffer::setFileName(FileName const & fname)
 {
bool const changed = fname != d->filename;
d->filename = fname;
+   d->refreshFileMonitor();
if (changed)
lyxvc().file_found_hook(fname);
setReadonly(d->filename.isReadOnly());
@@ -1360,6 +1380,7 @@ FileName Buffer::getBackupName() const {
 // Should probably be moved to somewhere else: BufferView? GuiView?
 bool Buffer::save() const
 {
+   FileMonitorBlocker block = d->blockFileMonitor();
docstring const file = makeDisplayPath(absFileName(), 20);
d->filename.refresh();
 
@@ -1375,7 +1396,7 @@ bool Buffer::save() const
}
 
// ask if the disk file has been externally modified (use checksum 
method)
-   if (fileName().exists() && isExternallyModified(checksum_method)) {
+   if (fileName().exists() && isChecksumModified()) {
docstring text =
bformat(_("Document %1$s has been externally modified. "
"Are you sure you want to overwrite this 
file?"), file);
@@ -2995,13 +3016,10 @@ bool Buffer::isClean() const
 }
 
 
-bool Buffer::isExternallyModified(CheckMethod method) const
+bool Buffer::isChecksumModified() const
 {
LASSERT(d->filename.exists(), return false);
-   // if method == timestamp, check timestamp before checksum
-   return (method == checksum_method
-   || d->timestamp_ != d->filename.lastModified())
-   && d->checksum_ != d->filename.checksum();
+   return d->checksum_ != d->filename.checksum();
 }
 
 
@@ -3031,6 +3049,7 @@ void Buffer::markClean() const
// autosave
d->bak_clean = true;
d->undo_.markDirty();
+   clearExternalModification();
 }
 
 
@@ -5298,5 +5317,41 @@ void Buffer::updateChangesPresent() const
 }
 
 
+void Buffer::Impl::refreshFileMonitor()
+{
+   if (file_monitor_ && file_monitor_->filename() == 
filename.absFileName())
+   return file_monitor_->refresh();
+
+   // The previous file monitor is invalid
+   // This also destroys the previous file monitor and all its connections
+   file_monitor_ = FileSystemWatcher::monitor(filename);
+   fileExternallyModified(false);
+   // file_monitor_ will be destroyed with *this, so it is not going to 
call a
+   // destroyed object method.
+   file_monitor_->connect([this](){ fileExternallyModified(true); });
+}
+
+
+void Buffer::Impl::fileExternallyModified(bool modified) const
+{
+   if (modified)
+   lyx_clean = bak_clean = false;
+   externally_modified_ = modified;
+   if (

[LyX/master] Implement FileMonitor as a wrapper for QFileSystemWatcher

2017-03-10 Thread Guillaume Munch
commit caa54e80ee410c0fa3cc9a1eea6588d68a92386b
Author: Guillaume Munch 
Date:   Mon Feb 27 23:46:10 2017 +0100

Implement FileMonitor as a wrapper for QFileSystemWatcher

The new file monitor supports both boost and qt signals. It is implemented 
in a
ressource-safe way.
---
 src/support/FileMonitor.h|6 +-
 src/support/FileMonitor2.cpp |  211 ++
 src/support/FileMonitor2.h   |  192 ++
 src/support/Makefile.am  |3 +
 4 files changed, 411 insertions(+), 1 deletions(-)

diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h
index d0d3741..efc8102 100644
--- a/src/support/FileMonitor.h
+++ b/src/support/FileMonitor.h
@@ -15,6 +15,9 @@
 #ifndef FILEMONITOR_H
 #define FILEMONITOR_H
 
+// TODO: Remove FileMonitor
+#include "support/FileMonitor2.h"
+
 #include 
 
 namespace lyx {
@@ -28,7 +31,8 @@ public:
/** Once monitoring begins, the file will be monitored every
 *  interval ms.
 *
-* FIXME: rewrite and simplify using an encapsulation of 
QFileSystemWatcher.
+* This is now obsoleted by FileMonitor2 based on QFileSystemWatcher.
+* FIXME: Remove FileMonitor
 */
FileMonitor(FileName const & file_with_path, int interval);
 
diff --git a/src/support/FileMonitor2.cpp b/src/support/FileMonitor2.cpp
new file mode 100644
index 000..2cf8cb9
--- /dev/null
+++ b/src/support/FileMonitor2.cpp
@@ -0,0 +1,211 @@
+/**
+ * \file FileMonitor.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Guillaume Munch
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include 
+
+#include "support/FileMonitor2.h"
+
+#include "support/debug.h"
+#include "support/FileName.h"
+#include "support/qstring_helpers.h"
+#include "support/unique_ptr.h"
+
+#include 
+#include 
+#include 
+
+#include 
+
+using namespace std;
+
+namespace lyx {
+namespace support {
+
+
+FileSystemWatcher & FileSystemWatcher::instance()
+{
+   // This thread-safe because QFileSystemWatcher is thread-safe.
+   static FileSystemWatcher f;
+   return f;
+}
+
+
+FileSystemWatcher::FileSystemWatcher()
+   : qwatcher_(make_unique())
+{}
+
+
+//static
+FileMonitorPtr FileSystemWatcher::monitor(FileName const & file_with_path)
+{
+   FileSystemWatcher & f = instance();
+   string const filename = file_with_path.absFileName();
+   weak_ptr & wptr = f.store_[filename];
+   if (shared_ptr mon = wptr.lock())
+   return make_unique(mon);
+   auto mon = make_shared(filename, f.qwatcher_.get());
+   wptr = mon;
+   return make_unique(mon);
+}
+
+
+//static
+void FileSystemWatcher::debug()
+{
+   FileSystemWatcher & f = instance();
+   QStringList q_files = f.qwatcher_->files();
+   for (pair> pair : f.store_) {
+   string const & name = pair.first;
+   if (!pair.second.expired()) {
+   if (!q_files.contains(toqstr(name)))
+   LYXERR0("Monitored but not QFileSystemWatched 
(bad): " << name);
+   else {
+   //LYXERR0("Monitored and QFileSystemWatched 
(good): " << name);
+   }
+   }
+   }
+   for (QString const & qname : q_files) {
+   string const name = fromqstr(qname);
+   weak_ptr & wptr = f.store_[name];
+   if (wptr.expired())
+   LYXERR0("QFileSystemWatched but not monitored (bad): " 
<< name);
+   }
+}
+
+
+FileMonitorGuard::FileMonitorGuard(string const & filename,
+   QFileSystemWatcher * qwatcher)
+   : filename_(filename), qwatcher_(qwatcher)
+{
+   QObject::connect(qwatcher, SIGNAL(fileChanged(QString const &)),
+this, SLOT(notifyChange(QString const &)));
+   if (qwatcher_->files().contains(toqstr(filename)))
+   LYXERR0("This file is already being QFileSystemWatched: " << 
filename
+   << ". This should not happen.");
+   refresh();
+}
+
+
+FileMonitorGuard::~FileMonitorGuard()
+{
+   qwatcher_->removePath(toqstr(filename_));
+}
+
+
+void FileMonitorGuard::refresh(bool new_file)
+{
+   QString const qfilename = toqstr(filename_);
+   if(!qwatcher_->files().contains(qfilename)) {
+   bool exists = QFile(qfilename).exists();
+   if (!exists || !qwatcher_->addPath(qfilename)) {
+   if (exists)
+   LYXERR(Debug::FILES,
+  "Could not add path to 
QFileSystemWatcher: "
+  << filename_);
+   QTimer::singleShot(1000, this, [=](){
+   refresh(new_file || !exists);
+   });
+   

[LyX/master] Nonsense for whoever insists on using gcc4.6 & qt4.8 in 2017

2017-03-10 Thread Guillaume Munch
commit 24f68aff8d2ba9139017ca3927eda1f1aaf039af
Author: Guillaume Munch 
Date:   Sat Mar 11 00:11:02 2017 +0100

Nonsense for whoever insists on using gcc4.6 & qt4.8 in 2017
---
 src/support/FileMonitor.cpp |   21 ++---
 src/support/FileMonitor.h   |   17 +
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp
index a55fd23..051 100644
--- a/src/support/FileMonitor.cpp
+++ b/src/support/FileMonitor.cpp
@@ -18,6 +18,7 @@
 #include "support/unique_ptr.h"
 
 #include 
+#include 
 #include 
 
 #include 
@@ -103,6 +104,7 @@ void FileMonitorGuard::refresh(bool new_file)
QString const qfilename = toqstr(filename_);
if(!qwatcher_->files().contains(qfilename)) {
bool exists = QFile(qfilename).exists();
+#if (QT_VERSION >= 0x05)
if (!exists || !qwatcher_->addPath(qfilename)) {
if (exists)
LYXERR(Debug::FILES,
@@ -111,6 +113,21 @@ void FileMonitorGuard::refresh(bool new_file)
QTimer::singleShot(1000, this, [=](){
refresh(new_file || !exists);
});
+#else
+   auto add_path = [&]() {
+   qwatcher_->addPath(qfilename);
+   return qwatcher_->files().contains(qfilename);
+   };
+   if (!exists || !add_path()) {
+   if (exists)
+   LYXERR(Debug::FILES,
+  "Could not add path to 
QFileSystemWatcher: "
+  << filename_);
+   if (new_file || !exists)
+   QTimer::singleShot(1000, this, 
SLOT(refreshTrue()));
+   else
+   QTimer::singleShot(1000, this, 
SLOT(refreshFalse()));
+#endif
} else if (exists && new_file)
Q_EMIT fileChanged();
}
@@ -199,9 +216,7 @@ FileMonitorBlockerGuard::~FileMonitorBlockerGuard()
// from QFileSystemWatcher that we meant to ignore are not going to be
// treated immediately, so we must yield to give us the opportunity to
// ignore them.
-   QTimer::singleShot(delay_, parent, [parent]() {
-   parent->connectToFileMonitorGuard();
-   });
+   QTimer::singleShot(delay_, parent, SLOT(connectToFileMonitorGuard()));
 }
 
 } // namespace support
diff --git a/src/support/FileMonitor.h b/src/support/FileMonitor.h
index 09d85e8..deca740 100644
--- a/src/support/FileMonitor.h
+++ b/src/support/FileMonitor.h
@@ -34,7 +34,7 @@ class FileName;
 
 class FileMonitor;
 class FileMonitorGuard;
-using FileMonitorPtr = std::unique_ptr;
+typedef std::unique_ptr FileMonitorPtr;
 
 ///
 /// Watch a file:
@@ -115,6 +115,14 @@ private Q_SLOTS:
/// Receive notifications from the QFileSystemWatcher
void notifyChange(QString const & path);
 
+   /// nonsense introduced for when QT_VERSION < 0x05, cannot be placed
+   /// between #ifdef
+   void refreshTrue() { refresh(true); }
+   /// nonsense introduced for when QT_VERSION < 0x05, cannot be placed
+   /// between #ifdef
+   void refreshFalse() { refresh(false); }
+
+
 private:
std::string const filename_;
QFileSystemWatcher * qwatcher_;
@@ -134,7 +142,7 @@ public:
 };
 
 
-using FileMonitorBlocker = std::shared_ptr;
+typedef std::shared_ptr FileMonitorBlocker;
 
 
 /// Main class
@@ -146,7 +154,7 @@ class FileMonitor : public QObject
 public:
FileMonitor(std::shared_ptr monitor);
 
-   using sig = boost::signals2::signal;
+   typedef boost::signals2::signal sig;
/// Connect and you'll be informed when the file has changed.
boost::signals2::connection connect(sig::slot_type const &);
/// disconnect all slots connected to the boost signal fileChanged_ or 
to
@@ -173,9 +181,10 @@ Q_SIGNALS:
 private Q_SLOTS:
/// Receive notifications from the FileMonitorGuard
void changed();
+   ///
+   void connectToFileMonitorGuard();
 
 private:
-   void connectToFileMonitorGuard();
// boost signal
sig fileChanged_;
// the unique watch for our file


[LyX/master] Remove legacy FileMonitor

2017-03-10 Thread Guillaume Munch
commit f96d7a8b2cb45e98382e2d88f1156e74e7898f5e
Author: Guillaume Munch 
Date:   Fri Mar 10 22:41:48 2017 +0100

Remove legacy FileMonitor
---
 src/support/FileMonitor.cpp  |  233 +++--
 src/support/FileMonitor.h|  201 
 src/support/FileMonitor2.cpp |  211 --
 src/support/FileMonitor2.h   |  192 --
 src/support/Makefile.am  |4 +-
 5 files changed, 288 insertions(+), 553 deletions(-)

diff --git a/src/support/FileMonitor.cpp b/src/support/FileMonitor.cpp
index bdd6444..a55fd23 100644
--- a/src/support/FileMonitor.cpp
+++ b/src/support/FileMonitor.cpp
@@ -3,7 +3,7 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author Angus Leeming
+ * \author Guillaume Munch
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -12,170 +12,199 @@
 
 #include "support/FileMonitor.h"
 
+#include "support/debug.h"
 #include "support/FileName.h"
-#include "support/Timeout.h"
+#include "support/qstring_helpers.h"
+#include "support/unique_ptr.h"
 
-#include "support/bind.h"
-#include 
+#include 
+#include 
+
+#include 
 
 using namespace std;
 
 namespace lyx {
 namespace support {
 
-class FileMonitor::Impl : public boost::signals2::trackable {
-public:
-
-   ///
-   Impl(FileName const & file_with_path, int interval);
-
-   ///
-   void monitorFile();
-
-   ///
-   FileName filename_;
 
-   ///
-   Timeout timer_;
-
-   /// This signal is emitted if the file is modified (has a new checksum).
-   FileMonitor::FileChangedSig fileChanged_;
-
-   /** We use these to ascertain whether a file (once loaded successfully)
-*  has changed.
-*/
-   time_t timestamp_;
-   ///
-   unsigned long checksum_;
-};
+FileSystemWatcher & FileSystemWatcher::instance()
+{
+   // This thread-safe because QFileSystemWatcher is thread-safe.
+   static FileSystemWatcher f;
+   return f;
+}
 
 
-FileMonitor::FileMonitor(FileName const & file_with_path, int interval)
-   : pimpl_(new Impl(file_with_path, interval))
+FileSystemWatcher::FileSystemWatcher()
+   : qwatcher_(make_unique())
 {}
 
 
-FileMonitor::~FileMonitor()
+//static
+FileMonitorPtr FileSystemWatcher::monitor(FileName const & file_with_path)
 {
-   delete pimpl_;
+   FileSystemWatcher & f = instance();
+   string const filename = file_with_path.absFileName();
+   weak_ptr & wptr = f.store_[filename];
+   if (shared_ptr mon = wptr.lock())
+   return make_unique(mon);
+   auto mon = make_shared(filename, f.qwatcher_.get());
+   wptr = mon;
+   return make_unique(mon);
 }
 
 
-void FileMonitor::reset(FileName const & file_with_path) const
+//static
+void FileSystemWatcher::debug()
 {
-   if (pimpl_->filename_ == file_with_path)
-   return;
-
-   bool const monitor = pimpl_->timer_.running();
-   if (monitor)
-   stop();
+   FileSystemWatcher & f = instance();
+   QStringList q_files = f.qwatcher_->files();
+   for (pair> pair : f.store_) {
+   string const & name = pair.first;
+   if (!pair.second.expired()) {
+   if (!q_files.contains(toqstr(name)))
+   LYXERR0("Monitored but not QFileSystemWatched 
(bad): " << name);
+   else {
+   //LYXERR0("Monitored and QFileSystemWatched 
(good): " << name);
+   }
+   }
+   }
+   for (QString const & qname : q_files) {
+   string const name = fromqstr(qname);
+   weak_ptr & wptr = f.store_[name];
+   if (wptr.expired())
+   LYXERR0("QFileSystemWatched but not monitored (bad): " 
<< name);
+   }
+}
 
-   pimpl_->filename_ = file_with_path;
 
-   if (monitor)
-   start();
+FileMonitorGuard::FileMonitorGuard(string const & filename,
+   QFileSystemWatcher * qwatcher)
+   : filename_(filename), qwatcher_(qwatcher)
+{
+   QObject::connect(qwatcher, SIGNAL(fileChanged(QString const &)),
+this, SLOT(notifyChange(QString const &)));
+   if (qwatcher_->files().contains(toqstr(filename)))
+   LYXERR0("This file is already being QFileSystemWatched: " << 
filename
+   << ". This should not happen.");
+   refresh();
 }
 
 
-FileName const & FileMonitor::filename() const
+FileMonitorGuard::~FileMonitorGuard()
 {
-   return pimpl_->filename_;
+   qwatcher_->removePath(toqstr(filename_));
 }
 
 
-void FileMonitor::start() const
+void FileMonitorGuard::refresh(bool new_file)
 {
-   if (monitoring())
-   return;
-
-   if (!pimpl_->filename_.exists())
-   return;
+   Q

[LyX/master] Clean-up

2017-03-10 Thread Guillaume Munch
commit 656bc46892c2041437111dfff697957530e75ec2
Author: Guillaume Munch 
Date:   Wed Mar 1 20:32:33 2017 +0100

Clean-up
---
 src/Buffer.cpp |   18 +-
 src/Buffer.h   |2 +-
 2 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index ac01cf4..5c46fb3 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -264,9 +264,8 @@ public:
/// Container for all sort of Buffer dependant errors.
map errorLists;
 
-   /// timestamp and checksum used to test if the file has been externally
-   /// modified. (Used to properly enable 'File->Revert to saved', bug 
4114).
-   time_t timestamp_;
+   /// checksum used to test if the file has been externally modified.  
Used to
+   /// double check whether the file had been externally modified when 
saving.
unsigned long checksum_;
 
///
@@ -436,7 +435,7 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, 
bool readonly_,
: owner_(owner), lyx_clean(true), bak_clean(true), unnamed(false),
  internal_buffer(false), read_only(readonly_), filename(file),
  file_fully_loaded(false), file_format(LYX_FORMAT), 
need_format_backup(false),
- ignore_parent(false),  toc_backend(owner), macro_lock(false), 
timestamp_(0),
+ ignore_parent(false),  toc_backend(owner), macro_lock(false),
  checksum_(0), wa_(0),  gui_(0), undo_(*owner), 
bibinfo_cache_valid_(false),
  bibfile_cache_valid_(false), cite_labels_valid_(false), 
preview_error_(false),
  inset(0), preview_loader_(0), cloned_buffer_(cloned_buffer),
@@ -3026,16 +3025,9 @@ bool Buffer::isChecksumModified() const
 void Buffer::saveCheckSum() const
 {
FileName const & file = d->filename;
-
file.refresh();
-   if (file.exists()) {
-   d->timestamp_ = file.lastModified();
-   d->checksum_ = file.checksum();
-   } else {
-   // in the case of save to a new file.
-   d->timestamp_ = 0;
-   d->checksum_ = 0;
-   }
+   d->checksum_ = file.exists() ? file.checksum()
+   : 0; // in the case of save to a new file.
 }
 
 
diff --git a/src/Buffer.h b/src/Buffer.h
index 957d54c..7327de3 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -231,7 +231,7 @@ private:
typedef std::map BufferMap;
///
void cloneWithChildren(BufferMap &, CloneList *) const;
-   /// save timestamp and checksum of the given file.
+   /// save checksum of the given file.
void saveCheckSum() const;
/// read a new file
ReadStatus readFile(support::FileName const & fn);


[LyX/master] buffer-export default

2017-03-10 Thread Guillaume Munch
commit 3dec5826dae76e89a80ea9a0404467f8200fa783
Author: Guillaume Munch 
Date:   Thu Mar 9 23:35:27 2017 +0100

buffer-export default
---
 src/Buffer.cpp|6 +++---
 src/LyX.cpp   |2 +-
 src/LyXAction.cpp |2 +-
 src/frontends/qt4/GuiView.cpp |2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index d01336e..6b41213 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -2534,7 +2534,7 @@ bool Buffer::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
enable = true;
break;
}
-   string format = (arg.empty() || arg == "*") ?
+   string format = (arg.empty() || arg == "default") ?
params().getDefaultOutputFormat() : to_utf8(arg);
size_t pos = format.find(' ');
if (pos != string::npos)
@@ -2643,7 +2643,7 @@ void Buffer::dispatch(FuncRequest const & func, 
DispatchResult & dr)
break;
 
case LFUN_BUFFER_EXPORT: {
-   string const format = (argument.empty() || argument == "*") ?
+   string const format = (argument.empty() || argument == 
"default") ?
params().getDefaultOutputFormat() : argument;
ExportStatus const status = doExport(format, false);
dr.setError(status != ExportSuccess);
@@ -4231,7 +4231,7 @@ Buffer::ExportStatus Buffer::doExport(string const & 
target, bool put_in_tempdir
if (pos != string::npos) {
dest_filename = target.substr(pos + 1, target.length() - pos - 
1);
format = target.substr(0, pos);
-   if (format == "*")
+   if (format == "default")
format = params().getDefaultOutputFormat();
runparams.export_folder = 
FileName(dest_filename).onlyPath().realPath();
FileName(dest_filename).onlyPath().createPath();
diff --git a/src/LyX.cpp b/src/LyX.cpp
index d7f3243..c88e205 100644
--- a/src/LyX.cpp
+++ b/src/LyX.cpp
@@ -1182,7 +1182,7 @@ int parse_help(string const &, string const &, string &)
  "  Tools->Preferences->File Handling->File 
Formats->Short Name\n"
  "  to see which parameter (which differs from 
the format name\n"
  "  in the File->Export menu) should be 
passed. To export to\n"
- "  the document's default output format, use 
'*'.\n"
+ "  the document's default output format, use 
'default'.\n"
  "  Note that the order of -e and -x switches 
matters.\n"
  "\t-E [--export-to] fmt filename\n"
  "  where fmt is the export format of choice 
(see --export),\n"
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 1ac74db..673cf3b 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -583,7 +583,7 @@ void LyXAction::init()
 want to start from and for the command that you want to
 apply to this format. Internally the control is then 
passed
 to #LFUN_BUFFER_EXPORT_CUSTOM.\n
-If absent or *, then the default output format of the
+If absent or "default", then the default output format 
of the
 document is used.
  If present, this argument provides the export 
destination
filename. Its containing folder will also be the 
destination
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 63bd4c6..b4d0810 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -3548,7 +3548,7 @@ void GuiView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
else
target_dir = doc_buffer->fileName().onlyPath();
 
-   string const format = (argument.empty() || argument == 
"*") ?
+   string const format = (argument.empty() || argument == 
"default") ?
doc_buffer->params().getDefaultOutputFormat() : 
argument;
 
if ((dest.empty() && doc_buffer->isUnnamed())


[LyX/master] Clarify dialog

2017-03-10 Thread Guillaume Munch
commit 22ce6636efc236aff26244180c9a46508b291aa3
Author: Guillaume Munch 
Date:   Sun Mar 5 23:55:59 2017 +0100

Clarify dialog
---
 src/frontends/qt4/GuiView.cpp |   15 ++-
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 52a783a..1f1ec61 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -3735,11 +3735,16 @@ void GuiView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
if (!doc_buffer->isClean()) {
docstring const file =

makeDisplayPath(doc_buffer->absFileName(), 20);
-   docstring text = bformat(_("Any changes will be 
lost. "
-   "Are you sure you want to revert to the 
saved version "
-   "of the document %1$s?"), file);
-   ret = Alert::prompt(_("Revert to saved 
document?"),
-   text, 1, 1, _("&Revert"), _("&Cancel"));
+   doc_buffer->notifiesExternalModification();
+   docstring text = 
doc_buffer->notifiesExternalModification() ?
+ _("Any changes will be lost. "
+   "Are you sure you want to load the 
version on disk "
+   "of the document %1$s?")
+   : _("Any changes will be lost. "
+   "Are you sure you want to revert to 
the saved version "
+   "of the document %1$s?");
+   ret = Alert::prompt(_("Revert to file on 
disk?"),
+   bformat(text, file), 1, 1, 
_("&Revert"), _("&Cancel"));
}
 
if (ret == 0) {


[LyX/master] Add option to ignore a parameter in InsetCommandParams

2017-03-10 Thread Guillaume Munch
commit 387ac780883f16ef8edb647c4b556d42f4cd33bf
Author: Guillaume Munch 
Date:   Tue Feb 14 21:16:39 2017 +0100

Add option to ignore a parameter in InsetCommandParams

It will not be saved to the file and will always be equal to a given default
value.
---
 src/insets/InsetCommandParams.cpp |   26 +-
 src/insets/InsetCommandParams.h   |   17 +++--
 2 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/src/insets/InsetCommandParams.cpp 
b/src/insets/InsetCommandParams.cpp
index 5ea28ff..1acb72f 100644
--- a/src/insets/InsetCommandParams.cpp
+++ b/src/insets/InsetCommandParams.cpp
@@ -99,8 +99,10 @@ static ParamInfo const & findInfo(InsetCode code, string 
const & cmdName)
 /
 
 ParamInfo::ParamData::ParamData(std::string const & s, ParamType t,
-   ParamHandling h)
-   : name_(s), type_(t), handling_(h)
+ParamHandling h, bool ignore,
+docstring default_value)
+   : name_(s), type_(t), handling_(h), ignore_(ignore),
+ default_value_(default_value)
 {}
 
 
@@ -130,9 +132,10 @@ bool ParamInfo::hasParam(std::string const & name) const
 
 
 void ParamInfo::add(std::string const & name, ParamType type,
-   ParamHandling handling)
-{ 
-   info_.push_back(ParamData(name, type, handling)); 
+ParamHandling handling, bool ignore,
+docstring default_value)
+{
+   info_.push_back(ParamData(name, type, handling, ignore, default_value));
 }
 
 
@@ -296,6 +299,11 @@ void InsetCommandParams::Read(Lexer & lex, Buffer const * 
buffer)
}
 
info_ = findInfo(insetCode_, cmdName_);
+
+   for (ParamInfo::ParamData const & param : info_)
+   if (param.ignore()) {
+   params_[param.name()] = param.defaultValue();
+   }

string token;
while (lex.isOK()) {
@@ -361,6 +369,8 @@ void InsetCommandParams::Write(ostream & os, Buffer const * 
buffer) const
ParamInfo::const_iterator it  = info_.begin();
ParamInfo::const_iterator end = info_.end();
for (; it != end; ++it) {
+   if (it->ignore())
+   continue;
string const & name = it->name();
string data = to_utf8((*this)[name]);
if (!data.empty()) {
@@ -538,6 +548,9 @@ docstring const & InsetCommandParams::operator[](string 
const & name) const
ParamMap::const_iterator data = params_.find(name);
if (data == params_.end() || data->second.empty())
return dummy;
+   ParamInfo::ParamData const & param = info_[name];
+   if (param.ignore())
+   return param.defaultValue();
return data->second;
 }
 
@@ -546,6 +559,9 @@ docstring & InsetCommandParams::operator[](string const & 
name)
 {
LATTEST(info_.hasParam(name));
// this will add the name in release mode
+   ParamInfo::ParamData const & param = info_[name];
+   if (param.ignore())
+   params_[name] = param.defaultValue();
return params_[name];
 }
 
diff --git a/src/insets/InsetCommandParams.h b/src/insets/InsetCommandParams.h
index 4107378..861565a 100644
--- a/src/insets/InsetCommandParams.h
+++ b/src/insets/InsetCommandParams.h
@@ -52,7 +52,9 @@ public:
// flag for all commands.
public:
///
-   ParamData(std::string const &, ParamType, ParamHandling = 
HANDLING_NONE);
+   ParamData(std::string const &, ParamType, ParamHandling = 
HANDLING_NONE,
+ bool ignore = false,
+ docstring default_value = docstring());
///
std::string name() const { return name_; }
///
@@ -62,6 +64,10 @@ public:
/// whether this is an optional LaTeX argument
bool isOptional() const;
///
+   bool ignore() const { return ignore_; }
+   ///
+   docstring const & defaultValue() const { return default_value_; 
}
+   ///
bool operator==(ParamData const &) const;
/// 
bool operator!=(ParamData const & rhs) const
@@ -73,11 +79,18 @@ public:
ParamType type_;
/// do we need special handling on latex output?
ParamHandling handling_;
+   ///
+   bool ignore_;
+   ///
+   docstring default_value_;
};
 
/// adds a new parameter
+   /// If ignore is true, then the parameter is never saved, and is always
+   /// given the default value.
void add(std::string const & name, ParamType type,
-ParamHandling = HANDLING_NONE);
+ParamHandling = HANDLING_NONE, bo

[LyX/master] New LFUN buffer-external-modification-clear

2017-03-10 Thread Guillaume Munch
commit 299242bb16e2fdd026ac975e8ac4d81e8dfef890
Author: Guillaume Munch 
Date:   Wed Mar 1 21:16:37 2017 +0100

New LFUN buffer-external-modification-clear
---
 src/FuncCode.h|1 +
 src/LyXAction.cpp |   10 ++
 src/frontends/qt4/GuiView.cpp |9 +
 3 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/src/FuncCode.h b/src/FuncCode.h
index ad9cb56..4ad5a78 100644
--- a/src/FuncCode.h
+++ b/src/FuncCode.h
@@ -468,6 +468,7 @@ enum FuncCode
LFUN_BRANCH_INVERT, // rgheck, 20160712
LFUN_LYX_ACTIVATE,  // skostysh, 20160804
LFUN_ICON_SIZE, // daniel, 20160712
+   LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR,// gm, 20170302
LFUN_LASTACTION // end of the table
 };
 
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 673cf3b..337 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -879,6 +879,16 @@ void LyXAction::init()
{ LFUN_BUFFER_WRITE_AS, "buffer-write-as", ReadOnly, Buffer },
 
 /*!
+ * \var lyx::FuncCode lyx::LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR
+ * \li Action: Clear the external modification flag on the current buffer.
+ * \li Syntax: buffer-external-modification-clear
+ * \li Origin: gm, 2 March 2017
+ * \endvar
+ */
+   { LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR,
+ "buffer-external-modification-clear", ReadOnly, Buffer },
+
+/*!
  * \var lyx::FuncCode lyx::LFUN_BUFFER_ZOOM_IN
  * \li Action: Increases the zoom of the screen fonts.
  * \li Syntax: buffer-zoom-in []
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 7ff8e04..e2e6555 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -1848,6 +1848,10 @@ bool GuiView::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
break;
}
 
+   case LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR:
+   enable = doc_buffer && 
doc_buffer->notifiesExternalModification();
+   break;
+
case LFUN_BUFFER_WRITE_AS:
case LFUN_BUFFER_EXPORT_AS:
enable = doc_buffer != 0;
@@ -3773,6 +3777,11 @@ void GuiView::dispatch(FuncRequest const & cmd, 
DispatchResult & dr)
break;
}
 
+   case LFUN_BUFFER_EXTERNAL_MODIFICATION_CLEAR:
+   LASSERT(doc_buffer, break);
+   doc_buffer->clearExternalModification();
+   break;
+
case LFUN_BUFFER_CLOSE:
closeBuffer();
break;


[LyX/master] Amend 63be456c8

2017-03-10 Thread Guillaume Munch
commit b034389e6def020d5201d59f6bab901453c3b5af
Author: Guillaume Munch 
Date:   Fri Mar 10 22:55:33 2017 +0100

Amend 63be456c8

Fix crash when clicking on math previews
---
 src/Cursor.cpp |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/Cursor.cpp b/src/Cursor.cpp
index 2de42ba..758cef9 100644
--- a/src/Cursor.cpp
+++ b/src/Cursor.cpp
@@ -2443,6 +2443,8 @@ void Cursor::moveToClosestEdge(int const x, bool const 
edit)
if (edit && (inset->hasSettings() || 
!inset->contextMenuName().empty()))
return;
CoordCache::Insets const & insetCache = 
bv().coordCache().getInsets();
+   if (!insetCache.has(inset))
+   return;
int const wid = insetCache.dim(inset).wid;
Point p = insetCache.xy(inset);
if (x > p.x_ + (wid + 1) / 2)


[LyX/master] Replace FileMonitor with FileMonitor2 in GraphicsCacheItem

2017-03-10 Thread Guillaume Munch
commit e3a13968139a7b9469060e2f10b7807c8e10339b
Author: Guillaume Munch 
Date:   Mon Mar 6 23:16:04 2017 +0100

Replace FileMonitor with FileMonitor2 in GraphicsCacheItem

Remove dead code
---
 src/graphics/GraphicsCacheItem.cpp |   25 +
 src/graphics/GraphicsCacheItem.h   |8 +---
 src/graphics/GraphicsLoader.cpp|9 -
 src/graphics/GraphicsLoader.h  |5 -
 4 files changed, 14 insertions(+), 33 deletions(-)

diff --git a/src/graphics/GraphicsCacheItem.cpp 
b/src/graphics/GraphicsCacheItem.cpp
index c698168..9eb449a 100644
--- a/src/graphics/GraphicsCacheItem.cpp
+++ b/src/graphics/GraphicsCacheItem.cpp
@@ -45,6 +45,8 @@ public:
///
Impl(FileName const & file, FileName const & doc_file);
 
+   void startMonitor();
+
/**
 *  If no file conversion is needed, then tryDisplayFormat() calls
 *  loadImage() directly.
@@ -97,7 +99,7 @@ public:
/// The document filename this graphic item belongs to
FileName const & doc_file_;
///
-   FileMonitor const monitor_;
+   FileMonitorPtr monitor_;
 
/// Is the file compressed?
bool zipped_;
@@ -167,20 +169,13 @@ void CacheItem::startLoading() const
 
 void CacheItem::startMonitoring() const
 {
-   if (!pimpl_->monitor_.monitoring())
-   pimpl_->monitor_.start();
+   pimpl_->startMonitor();
 }
 
 
 bool CacheItem::monitoring() const
 {
-   return pimpl_->monitor_.monitoring();
-}
-
-
-unsigned long CacheItem::checksum() const
-{
-   return pimpl_->monitor_.checksum();
+   return (bool)pimpl_->monitor_;
 }
 
 
@@ -209,12 +204,18 @@ boost::signals2::connection CacheItem::connect(slot_type 
const & slot) const
 
 CacheItem::Impl::Impl(FileName const & file, FileName const & doc_file)
: filename_(file), doc_file_(doc_file),
- monitor_(file, 2000),
  zipped_(false),
  remove_loaded_file_(false),
  status_(WaitingToLoad)
+{}
+
+
+void CacheItem::Impl::startMonitor()
 {
-   monitor_.connect(bind(&Impl::startLoading, this));
+   if (monitor_)
+   return;
+   monitor_ = FileSystemWatcher::monitor(filename_);
+   monitor_->connect([=](){ startLoading(); });
 }
 
 
diff --git a/src/graphics/GraphicsCacheItem.h b/src/graphics/GraphicsCacheItem.h
index ee2348d..b6d7d41 100644
--- a/src/graphics/GraphicsCacheItem.h
+++ b/src/graphics/GraphicsCacheItem.h
@@ -66,11 +66,6 @@ public:
void startMonitoring() const;
///
bool monitoring() const;
-   /** Returns the check checksum of filename() so that, for example, you 
can
-*  ascertain whether to output a new PostScript version of the file
-*  for a LaTeX run.
-*/
-   unsigned long checksum() const;
 
/** Get the image associated with filename().
 *  If the image is not yet loaded, returns 0.
@@ -85,8 +80,7 @@ public:
/** Connect and you'll be informed when the loading status of the image
 *  changes.
 */
-   typedef boost::signals2::signal sig_type;
-   typedef sig_type::slot_type slot_type;
+   typedef boost::signals2::signal::slot_type slot_type;
///
boost::signals2::connection connect(slot_type const &) const;
 
diff --git a/src/graphics/GraphicsLoader.cpp b/src/graphics/GraphicsLoader.cpp
index 987a973..617ce24 100644
--- a/src/graphics/GraphicsLoader.cpp
+++ b/src/graphics/GraphicsLoader.cpp
@@ -328,15 +328,6 @@ bool Loader::monitoring() const
 }
 
 
-unsigned long Loader::checksum() const
-{
-   if (!pimpl_->cached_item_)
-   return 0;
-
-   return pimpl_->cached_item_->checksum();
-}
-
-
 FileName const & Loader::filename() const
 {
static FileName const empty;
diff --git a/src/graphics/GraphicsLoader.h b/src/graphics/GraphicsLoader.h
index 8b97114..0b58857 100644
--- a/src/graphics/GraphicsLoader.h
+++ b/src/graphics/GraphicsLoader.h
@@ -81,11 +81,6 @@ public:
void startMonitoring() const;
///
bool monitoring() const;
-   /** Returns the check checksum of filename() so that, for example, you 
can
-*  ascertain whether to output a new PostScript version of the file
-*  for a LaTeX run.
-*/
-   unsigned long checksum() const;
 
/// How far have we got in loading the image?
ImageStatus status() const;


[LyX/master] Whitespace

2017-03-10 Thread Guillaume Munch
commit 7c123507a4a5a79ef8cec5bb85375ce7ca99ca18
Author: Guillaume Munch 
Date:   Tue Feb 28 22:24:51 2017 +0100

Whitespace
---
 src/Buffer.cpp |   10 +-
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 2bc454b..ac01cf4 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -1411,12 +1411,12 @@ bool Buffer::save() const
 
// if the file does not yet exist, none of the backup activity
// that follows is necessary
-  if (!fileName().exists()) {
+   if (!fileName().exists()) {
if (!writeFile(fileName()))
-  return false;
-markClean();
-return true;
-  }
+   return false;
+   markClean();
+   return true;
+   }
 
// we first write the file to a new name, then move it to its
// proper location once that has been done successfully. that


[LyX/master] Disable edition when external modifications are detected

2017-03-10 Thread Guillaume Munch
commit 0cb85e920666e8a47cb74ce96711fdcae8168862
Author: Guillaume Munch 
Date:   Wed Mar 1 22:03:44 2017 +0100

Disable edition when external modifications are detected

Introduce a distinction between being read-only and having the read-only 
flag. A
buffer is read-only if either it has been externally modified or if it has 
the
read-only flag.
---
 src/Buffer.cpp|   18 --
 src/Buffer.h  |6 +-
 src/BufferView.cpp|5 -
 src/LyXVC.cpp |4 ++--
 src/VCBackend.cpp |4 ++--
 src/frontends/qt4/GuiView.cpp |   13 +++--
 src/frontends/qt4/GuiWorkArea.cpp |6 +++---
 src/frontends/qt4/Menus.cpp   |4 ++--
 8 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 5c46fb3..b220ee3 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -2535,7 +2535,7 @@ bool Buffer::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
switch (cmd.action()) {
 
case LFUN_BUFFER_TOGGLE_READ_ONLY:
-   flag.setOnOff(isReadonly());
+   flag.setOnOff(hasReadonlyFlag());
break;
 
// FIXME: There is need for a command-line import.
@@ -2659,7 +2659,7 @@ void Buffer::dispatch(FuncRequest const & func, 
DispatchResult & dr)
dr.setMessage(log);
}
else
-   setReadonly(!isReadonly());
+   setReadonly(!hasReadonlyFlag());
break;
 
case LFUN_BUFFER_EXPORT: {
@@ -3262,12 +3262,18 @@ void Buffer::setLayoutPos(string const & path)
 }
 
 
-bool Buffer::isReadonly() const
+bool Buffer::hasReadonlyFlag() const
 {
return d->read_only;
 }
 
 
+bool Buffer::isReadonly() const
+{
+   return hasReadonlyFlag() || notifiesExternalModification();
+}
+
+
 void Buffer::setParent(Buffer const * buffer)
 {
// Avoids recursive include.
@@ -4144,7 +4150,7 @@ void Buffer::moveAutosaveFile(support::FileName const & 
oldauto) const
 bool Buffer::autoSave() const
 {
Buffer const * buf = d->cloned_buffer_ ? d->cloned_buffer_ : this;
-   if (buf->d->bak_clean || isReadonly())
+   if (buf->d->bak_clean || hasReadonlyFlag())
return true;
 
message(_("Autosaving current document..."));
@@ -4541,7 +4547,7 @@ Buffer::ReadStatus Buffer::loadEmergency()
ReadStatus const ret_llf = loadThisLyXFile(emergencyFile);
bool const success = (ret_llf == ReadSuccess);
if (success) {
-   if (isReadonly()) {
+   if (hasReadonlyFlag()) {
Alert::warning(_("File is read-only"),
bformat(_("An emergency file is 
successfully loaded, "
"but the original file %1$s is marked 
read-only. "
@@ -4604,7 +4610,7 @@ Buffer::ReadStatus Buffer::loadAutosave()
ReadStatus const ret_llf = loadThisLyXFile(autosaveFile);
// the file is not saved if we load the autosave file.
if (ret_llf == ReadSuccess) {
-   if (isReadonly()) {
+   if (hasReadonlyFlag()) {
Alert::warning(_("File is read-only"),
bformat(_("A backup file is 
successfully loaded, "
"but the original file %1$s is marked 
read-only. "
diff --git a/src/Buffer.h b/src/Buffer.h
index 7327de3..d483de9 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -471,9 +471,13 @@ public:
/// thing from whichever Buffer it is called.
ListOfBuffers allRelatives() const;
 
-   /// Is buffer read-only?
+   /// Is buffer read-only? True if it has either the read-only flag or the
+   /// externally modified flag.
bool isReadonly() const;
 
+   /// Does the buffer have the read-only flag?
+   bool hasReadonlyFlag() const;
+
/// Set buffer read-only flag
void setReadonly(bool flag = true);
 
diff --git a/src/BufferView.cpp b/src/BufferView.cpp
index d017db0..a6ae1d4 100644
--- a/src/BufferView.cpp
+++ b/src/BufferView.cpp
@@ -1028,7 +1028,10 @@ bool BufferView::getStatus(FuncRequest const & cmd, 
FuncStatus & flag)
if (buffer_.isReadonly()
&& !lyxaction.funcHasFlag(act, LyXAction::ReadOnly)
&& !lyxaction.funcHasFlag(act, LyXAction::NoBuffer)) {
-   flag.message(from_utf8(N_("Document is read-only")));
+   if (buffer_.hasReadonlyFlag())
+   flag.message(from_utf8(N_("Document is read-only")));
+   else
+   flag.message(from_utf8(N_("Document has been modified 
externally")));
flag.setEnabled(false);
return true;
}
d

[LyX/master] Update fr.po

2017-03-10 Thread jpc
commit 8e9fb2eabcbd2386b2f3489ccb61e56d8b5c8e01
Author: jpc 
Date:   Fri Mar 10 19:14:09 2017 +0100

   Update fr.po
---
 po/fr.gmo |  Bin 526008 -> 526220 bytes
 po/fr.po  | 1096 +++--
 2 files changed, 552 insertions(+), 544 deletions(-)

diff --git a/po/fr.gmo b/po/fr.gmo
index 5248b28..6635e32 100644
Binary files a/po/fr.gmo and b/po/fr.gmo differ
diff --git a/po/fr.po b/po/fr.po
index b1e0b90..83c2401 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -322,8 +322,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: LyX 2.2\n"
 "Report-Msgid-Bugs-To: lyx-de...@lists.lyx.org\n"
-"POT-Creation-Date: 2017-02-28 15:21+0100\n"
-"PO-Revision-Date: 2017-02-28 17:00+0100\n"
+"POT-Creation-Date: 2017-03-10 18:37+0100\n"
+"PO-Revision-Date: 2017-03-10 18:47+0100\n"
 "Last-Translator: Jean-Pierre Chrétien \n"
 "Language-Team: lyxfr\n"
 "Language: fr\n"
@@ -614,7 +614,7 @@ msgstr "A&jouter"
 #: src/frontends/qt4/ui/BibtexUi.ui:296 src/frontends/qt4/ui/ChangesUi.ui:91
 #: src/frontends/qt4/ui/SendtoUi.ui:92 src/frontends/qt4/ui/ShortcutUi.ui:65
 #: src/buffer_funcs.cpp:129 src/frontends/qt4/ButtonController.cpp:238
-#: src/frontends/qt4/GuiApplication.cpp:1819
+#: src/frontends/qt4/GuiApplication.cpp:1817
 #: src/frontends/qt4/GuiCompare.cpp:192
 msgid "Cancel"
 msgstr "Annuler"
@@ -1010,8 +1010,8 @@ msgid "Remove the selected branch"
 msgstr "Enlever la branche sélectionnée"
 
 #: src/frontends/qt4/ui/BranchesUi.ui:136
-#: src/frontends/qt4/ui/IndicesUi.ui:165 src/Buffer.cpp:4547
-#: src/Buffer.cpp:4560
+#: src/frontends/qt4/ui/IndicesUi.ui:165 src/Buffer.cpp:4550
+#: src/Buffer.cpp:4563
 msgid "&Remove"
 msgstr "&Enlever"
 
@@ -1044,8 +1044,8 @@ msgstr "Ajouter &tout"
 #: src/frontends/qt4/ui/CompareHistoryUi.ui:205
 #: src/frontends/qt4/ui/DocumentUi.ui:84 src/frontends/qt4/ui/IndexUi.ui:78
 #: src/frontends/qt4/ui/ListingsUi.ui:559
-#: src/frontends/qt4/ui/PrintindexUi.ui:108 src/Buffer.cpp:1382
-#: src/Buffer.cpp:4521 src/Buffer.cpp:4585 src/LyXVC.cpp:114 src/LyXVC.cpp:304
+#: src/frontends/qt4/ui/PrintindexUi.ui:108 src/Buffer.cpp:1383
+#: src/Buffer.cpp:4524 src/Buffer.cpp:4588 src/LyXVC.cpp:114 src/LyXVC.cpp:304
 #: src/buffer_funcs.cpp:78 src/frontends/qt4/GuiBranches.cpp:219
 #: src/frontends/qt4/GuiClipboard.cpp:247
 #: src/frontends/qt4/GuiDocument.cpp:2209
@@ -1233,7 +1233,7 @@ msgstr "Série de police"
 #: lib/layouts/europasscv.layout:380 lib/layouts/europecv.layout:246
 #: lib/layouts/europecv.layout:252 lib/layouts/moderncv.layout:467
 #: src/frontends/qt4/GuiDocument.cpp:1451 src/frontends/qt4/GuiPrefs.cpp:2370
-#: src/frontends/qt4/Menus.cpp:893
+#: src/frontends/qt4/Menus.cpp:902
 msgid "Language"
 msgstr "Langue"
 
@@ -6774,8 +6774,8 @@ msgstr "Solution \\thesolution."
 msgid "Summary"
 msgstr "Résumé"
 
-#: lib/layouts/AEA.layout:300 src/frontends/qt4/Menus.cpp:1692
-#: src/frontends/qt4/Menus.cpp:1707
+#: lib/layouts/AEA.layout:300 src/frontends/qt4/Menus.cpp:1701
+#: src/frontends/qt4/Menus.cpp:1716
 msgid "Caption"
 msgstr "Légende"
 
@@ -7423,7 +7423,7 @@ msgstr "SousSousSection"
 #: lib/layouts/scrlettr.layout:165 lib/layouts/scrlttr2.layout:244
 #: lib/layouts/siamltex.layout:237 lib/layouts/stdtitle.inc:54
 #: lib/layouts/svcommon.inc:369 lib/layouts/tufte-book.layout:43
-#: lib/ui/stdmenus.inc:395
+#: lib/ui/stdmenus.inc:397
 msgid "Date"
 msgstr "Date"
 
@@ -17628,71 +17628,71 @@ msgstr "Unicode (XeTeX) (utf8)"
 msgid "ASCII"
 msgstr "ASCII"
 
-#: lib/ui/stdcontext.inc:30 lib/ui/stdmenus.inc:456
+#: lib/ui/stdcontext.inc:30 lib/ui/stdmenus.inc:458
 msgid "Array Environment|y"
 msgstr "Environnement tableau|b"
 
-#: lib/ui/stdcontext.inc:31 lib/ui/stdmenus.inc:457
+#: lib/ui/stdcontext.inc:31 lib/ui/stdmenus.inc:459
 msgid "Cases Environment|C"
 msgstr "Environnement cas|c"
 
-#: lib/ui/stdcontext.inc:32 lib/ui/stdmenus.inc:458
+#: lib/ui/stdcontext.inc:32 lib/ui/stdmenus.inc:460
 msgid "Aligned Environment|l"
 msgstr "Environnement Aligné|v"
 
-#: lib/ui/stdcontext.inc:33 lib/ui/stdmenus.inc:459
+#: lib/ui/stdcontext.inc:33 lib/ui/stdmenus.inc:461
 msgid "AlignedAt Environment|v"
 msgstr "Environnement AlignéSur|é"
 
-#: lib/ui/stdcontext.inc:34 lib/ui/stdmenus.inc:460
+#: lib/ui/stdcontext.inc:34 lib/ui/stdmenus.inc:462
 msgid "Gathered Environment|h"
 msgstr "Environnement Rassemblé|m"
 
-#: lib/ui/stdcontext.inc:35 lib/ui/stdmenus.inc:461
+#: lib/ui/stdcontext.inc:35 lib/ui/stdmenus.inc:463
 msgid "Split Environment|S"
 msgstr "Environnement disjoint|j"
 
-#: lib/ui/stdcontext.inc:37 lib/ui/stdmenus.inc:463
+#: lib/ui/stdcontext.inc:37 lib/ui/stdmenus.inc:465
 msgid "Delimiters...|r"
 msgstr "Délimiteurs...|r"
 
-#: lib/ui/stdcontext.inc:38 lib/ui/stdmenus.inc:464
+#: lib/ui/stdcontext.inc:38 lib/ui/stdmenus.inc:466
 msgid "Matrix...|x"
 msgstr "Matrice...|t"
 
-#: lib/ui/stdcontext.inc:39 lib/ui/stdmenus.inc:465
+#: lib/ui/stdcontext.inc:39 lib/ui/stdmenus.inc:467
 msgid "Macro|o"
 msgstr "Macro|o"
 
-#: lib/ui/stdcontext.inc:43 li

[LyX/master] Class agutex.cls is obsolete: information given in the LyX template

2017-03-10 Thread jpc
commit ac06a54163d7867c1df8852de51ee411e2dd631f
Author: jpc 
Date:   Fri Mar 10 19:11:22 2017 +0100

 Class agutex.cls is obsolete: information given in the LyX template
---
 lib/templates/AGUTeX.lyx |   23 +--
 1 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/lib/templates/AGUTeX.lyx b/lib/templates/AGUTeX.lyx
index 056fa2f..d648055 100644
--- a/lib/templates/AGUTeX.lyx
+++ b/lib/templates/AGUTeX.lyx
@@ -1,5 +1,5 @@
-#LyX 2.2 created this file. For more info see http://www.lyx.org/
-\lyxformat 508
+#LyX 2.3 created this file. For more info see http://www.lyx.org/
+\lyxformat 534
 \begin_document
 \begin_header
 \save_transient_properties true
@@ -59,6 +59,7 @@ theorems-std
 \font_osf false
 \font_sf_scale 100 100
 \font_tt_scale 100 100
+\use_microtype false
 \graphics default
 \default_output_format default
 \output_sync 0
@@ -96,7 +97,8 @@ theorems-std
 \tocdepth 3
 \paragraph_separation indent
 \paragraph_indentation default
-\quotes_language english
+\quotes_style english
+\dynamic_quotes 0
 \papercolumns 1
 \papersides 1
 \paperpagestyle default
@@ -114,9 +116,9 @@ theorems-std
 status open
 
 \begin_layout Plain Layout
-This is a template \SpecialChar LyX
- file for articles to be submitted to Journals of the
- American Geophysical Union (AGU).
+This is an OBSOLETE template \SpecialChar LyX
+ file for articles to be submitted to Journals
+ of the American Geophysical Union (AGU).
  How to install the AGU\SpecialChar TeX
  \SpecialChar LaTeX
  class to your \SpecialChar LaTeX
@@ -131,7 +133,12 @@ http://wiki.lyx.org/Examples/AGUTeX
 
 \end_inset
 
+: the new AGU class name is 
+\family sans
+agujournal.cls
+\family default
 .
+ A template LyX file and the corresponding layout are pending.
 \end_layout
 
 \end_inset
@@ -385,6 +392,7 @@ A & = & \prod_{i=1}^{\infty}B\nonumber \\
 \begin_inset CommandInset citation
 LatexCommand citet
 key "jskilby,inproceedings-minimal"
+literal "true"
 
 \end_inset
 
@@ -393,6 +401,7 @@ key "jskilby,inproceedings-minimal"
 \begin_inset CommandInset citation
 LatexCommand citep
 key "jskilbye"
+literal "true"
 
 \end_inset
 
@@ -569,6 +578,7 @@ Or plain bibliography:
 LatexCommand bibitem
 label "\\textit{Kilby}(2008)"
 key "jskilby"
+literal "true"
 
 \end_inset
 
@@ -591,6 +601,7 @@ IEEE Trans.
 LatexCommand bibitem
 label "\\textit{Kilby et al.}(2008)"
 key "jskilbye"
+literal "true"
 
 \end_inset
 


[LyX/master] Experiment: limit size of strings read from lib/symbols

2017-03-10 Thread Jean-Marc Lasgouttes
commit 9a013637bbe7c35dc90cb28ff874da99133a1f8b
Author: Jean-Marc Lasgouttes 
Date:   Fri Mar 10 16:29:09 2017 +0100

Experiment: limit size of strings read from lib/symbols

Coverity complains that we might read strings that are arbitrary
large, and that this can be a security issue. This is a problem in
particular, when we feed these strings to from_utf8(), which coverity
flags as dangerous for some reason.

The best solution would be IMO to model from_utf8() properly, but I do
not know how to do that. Here I try a different solution, where I
cannot read a string larger than 64k from the file.

Let's see whether this removes part of coverity warnings.
---
 src/mathed/MathFactory.cpp |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/src/mathed/MathFactory.cpp b/src/mathed/MathFactory.cpp
index 3198f80..2cd045b 100644
--- a/src/mathed/MathFactory.cpp
+++ b/src/mathed/MathFactory.cpp
@@ -74,6 +74,7 @@
 #include "LyX.h" // use_gui
 #include "OutputParams.h"
 
+#include 
 
 using namespace std;
 using namespace lyx::support;
@@ -188,7 +189,7 @@ void initSymbols()
string extra;
string xmlname;
bool hidden = false;
-   is >> macro >> requires;
+   is >> setw(65536) >> macro >> requires;
if ((is >> xmlname)) {
extra = requires;
if (!(is >> requires))


[LyX/master] Small cleanup to LayoutBox and CategorizedCombo

2017-03-10 Thread Jean-Marc Lasgouttes
commit 0f220503ff9f0b571ce3d3f8ee5941cf344edff7
Author: Jean-Marc Lasgouttes 
Date:   Fri Mar 10 15:54:27 2017 +0100

Small cleanup to LayoutBox and CategorizedCombo

Coverity does not find it obvious that p is never negative. Normally
it is the case (because the items have been filtered), but it is
better to play safe.
---
 src/frontends/qt4/CategorizedCombo.cpp |4 ++--
 src/frontends/qt4/LayoutBox.cpp|4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/frontends/qt4/CategorizedCombo.cpp 
b/src/frontends/qt4/CategorizedCombo.cpp
index 8e4fc64..4509e79 100644
--- a/src/frontends/qt4/CategorizedCombo.cpp
+++ b/src/frontends/qt4/CategorizedCombo.cpp
@@ -271,10 +271,10 @@ QString CCItemDelegate::underlineFilter(QString const & 
s) const
// step through data item and put "(x)" for every matching character
QString r;
int lastp = -1;
-   cc_->filter();
for (int i = 0; i < f.length(); ++i) {
int p = s.indexOf(f[i], lastp + 1, Qt::CaseInsensitive);
-   LASSERT(p != -1, /**/);
+   if (p < 0)
+   continue;
if (lastp == p - 1 && lastp != -1) {
// remove ")" and append "x)"
r = r.left(r.length() - 4) + s[p] + "";
diff --git a/src/frontends/qt4/LayoutBox.cpp b/src/frontends/qt4/LayoutBox.cpp
index 09dd878..8945ed0 100644
--- a/src/frontends/qt4/LayoutBox.cpp
+++ b/src/frontends/qt4/LayoutBox.cpp
@@ -320,10 +320,10 @@ QString LayoutItemDelegate::underlineFilter(QString const 
& s) const
// step through data item and put "(x)" for every matching character
QString r;
int lastp = -1;
-   layout_->filter();
for (int i = 0; i < f.length(); ++i) {
int p = s.indexOf(f[i], lastp + 1, Qt::CaseInsensitive);
-   LASSERT(p != -1, continue);
+   if (p < 0)
+   continue;
if (lastp == p - 1 && lastp != -1) {
// remove ")" and append "x)"
r = r.left(r.length() - 4) + s[p] + "";


[LyX/master] Add label 'defaultoutput' to export tests using document default output format

2017-03-10 Thread Kornel Benko
commit c99e2f1fad4f19d7a9f7114850558bcd82f83c98
Author: Kornel Benko 
Date:   Fri Mar 10 14:32:21 2017 +0100

Add label 'defaultoutput' to export tests using document default output 
format
---
 development/autotests/ExportTests.cmake |  103 +--
 1 files changed, 56 insertions(+), 47 deletions(-)

diff --git a/development/autotests/ExportTests.cmake 
b/development/autotests/ExportTests.cmake
index 3f91b13..ad99163 100644
--- a/development/autotests/ExportTests.cmake
+++ b/development/autotests/ExportTests.cmake
@@ -48,7 +48,7 @@ macro(initLangVars varname)
   endforeach()
 endmacro()
 
-macro(getoutputformats filepath varname)
+macro(getoutputformats filepath varname format_set)
   file(STRINGS "${filepath}" lines)
   # What should we test, if default_output_format is not defined?
   # For now we test everything ...
@@ -58,18 +58,21 @@ macro(getoutputformats filepath varname)
   set(_format ${CMAKE_MATCH_1})
   if(_format STREQUAL "default")
 set(out_formats "xhtml" ${DVI_FORMATS} ${PDF_FORMATS})
-  elseif(_format STREQUAL "pdf2" AND "${filepath}" MATCHES "/doc/")
-set(out_formats "xhtml" ${DVI_FORMATS} ${PDF_FORMATS})
-  elseif(_format MATCHES "pdf$")
-set(out_formats "xhtml" ${PDF_FORMATS})
-  elseif(_format MATCHES "dvi$")
-set(out_formats "xhtml" ${DVI_FORMATS})
-  elseif(_format MATCHES "xhtml")
-set(out_formats "xhtml")
   else()
-# Respect all other output formats
-# like "eps3"
-set(out_formats "xhtml" ${_format})
+set(${format_set} ${_format})
+if(_format STREQUAL "pdf2" AND "${filepath}" MATCHES "/doc/")
+  set(out_formats "xhtml" ${DVI_FORMATS} ${PDF_FORMATS})
+elseif(_format MATCHES "pdf$")
+  set(out_formats "xhtml" ${PDF_FORMATS})
+elseif(_format MATCHES "dvi$")
+  set(out_formats "xhtml" ${DVI_FORMATS})
+elseif(_format MATCHES "xhtml")
+  set(out_formats "xhtml")
+else()
+  # Respect all other output formats
+  # like "eps3"
+  set(out_formats "xhtml" ${_format})
+endif()
   endif()
   break()
 endif()
@@ -161,10 +164,10 @@ macro(maketestname testname inverted listinverted 
listignored listunreliable lis
   findexpr(foundsuspended ${testname} ${listsuspendedx} sublabel3)
   set(${inverted} 1)
   if (foundsuspended)
-   set(sublabel "suspended" ${sublabel} ${sublabel2} ${sublabel3})
-   list(REMOVE_ITEM sublabel "export" "inverted" )
+set(sublabel "suspended" ${sublabel} ${sublabel2} ${sublabel3})
+list(REMOVE_ITEM sublabel "export" "inverted" )
   else()
-   set(sublabel "inverted" ${sublabel} ${sublabel2} ${sublabel3})
+set(sublabel "inverted" ${sublabel} ${sublabel2} ${sublabel3})
   endif()
 else()
   set(${inverted} 0)
@@ -218,12 +221,12 @@ macro(loadTestList filename resList depth splitlangs)
 list(REMOVE_DUPLICATES mylabels)
 set(sublabel ${_newl})
   else()
-   if (${splitlangs} MATCHES "ON")
- string(REGEX REPLACE "(\\/|\\||\\(|\\))" "  " _vxx ${_newl})
- string(REGEX MATCHALL " ([a-z][a-z](_[A-Z][A-Z])?) " _vx ${_vxx})
-   else()
- set(_vx OFF)
-   endif()
+if (${splitlangs} MATCHES "ON")
+  string(REGEX REPLACE "(\\/|\\||\\(|\\))" "  " _vxx ${_newl})
+  string(REGEX MATCHALL " ([a-z][a-z](_[A-Z][A-Z])?) " _vx ${_vxx})
+else()
+  set(_vx OFF)
+endif()
 if(_vx)
   foreach(_v ${_vx})
 string(REGEX REPLACE " " "" _v ${_v})
@@ -377,7 +380,8 @@ foreach(libsubfolderx autotests/export lib/doc lib/examples 
lib/templates autote
   setmarkedtestlabel(${TestName} ${mytestlabel})
   #set_tests_properties(${TestName} PROPERTIES RUN_SERIAL ON)
 endif()
-getoutputformats("${LIBSUB_SRC_DIR}/${f}.lyx" formatlist)
+set(default_output_format)
+getoutputformats("${LIBSUB_SRC_DIR}/${f}.lyx" formatlist 
default_output_format)
 foreach(format ${formatlist})
   if(format MATCHES "dvi3|pdf4|pdf5")
 set(fonttypes "texF" "systemF")
@@ -387,24 +391,24 @@ foreach(libsubfolderx autotests/export lib/doc 
lib/examples lib/templates autote
   foreach(fonttype ${fonttypes})
 if (format MATCHES "pdf2" AND f MATCHES "latex/unicodesymbols")
   #message(STATUS "Test ${TestName} matches Unicode encodings")
- # test_encodings does not include "default", since it should be 
covered
- # by one of the supplied encodings
+  # test_encodings does not include "default", since it should be 
covered
+  # by one of the supplied encodings
   set(test_encodings "ascii" "utf8x" "armscii8" "applemac"
-   "cp437" "cp437de" "cp850" "cp852"
-   "cp855" "cp862" "cp865"
-   "cp866" "cp1250" "cp1251" "cp1252"
-   "cp1255" "cp1256" "cp1257"
-   "koi8-r" "koi8-u"
-

[LyX/master] Be careful about unparsable bibtex years

2017-03-10 Thread Jean-Marc Lasgouttes
commit e2f2915f8edcc558e7d41b6e9bf8e0a6838ba47d
Author: Jean-Marc Lasgouttes 
Date:   Fri Mar 10 10:32:38 2017 +0100

Be careful about unparsable bibtex years

Handle gracefully the case where the regex that parses a year fails.

This is a fixup to ba171930 (spotted by coverity).
---
 src/BiblioInfo.cpp |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/src/BiblioInfo.cpp b/src/BiblioInfo.cpp
index 5e2c7db..bfde294 100644
--- a/src/BiblioInfo.cpp
+++ b/src/BiblioInfo.cpp
@@ -417,7 +417,9 @@ docstring const BibTeXInfo::getYear() const
static regex const ereg(".*/[-]?([\\d]{4}).*");
smatch sm;
string const date = to_utf8(year);
-   regex_match(date, sm, yreg);
+   if (!regex_match(date, sm, yreg))
+   // cannot parse year.
+   return docstring();
year = from_ascii(sm[1]);
// check for an endyear
if (regex_match(date, sm, ereg))