+/// make sure the document is saved
+static bool ensureBufferClean(Buffer * buffer)
+{
+ LASSERT(buffer, return false);
+ if (buffer->isClean() && !buffer->isUnnamed())
+ return true;
+
+ docstring const file = buffer->fileName().displayName(30);
+ docstring title;
+ docstring text;
+ if (!buffer->isUnnamed()) {
+ text = bformat(_("The document %1$s has unsaved "
+ "changes.\n\nDo you want to save "
+ "the document?"), file);
+ title = _("Save changed document?");
+
+ } else {
+ text = bformat(_("The document %1$s has not been "
+ "saved yet.\n\nDo you want to save "
+ "the document?"), file);
+ title = _("Save new document?");
+ }
+ int const ret = Alert::prompt(title, text, 0, 1, _("&Save"), _("&Cancel"));
+
+ if (ret == 0)
+ dispatch(FuncRequest(LFUN_BUFFER_WRITE));
+
+ return buffer->isClean() && !buffer->isUnnamed();
+}
+
+
+void GuiView::reloadBuffer()
+{
+ Buffer * buf = &documentBufferView()->buffer();
+ buf->reload();
+}
+
+
+void GuiView::checkExternallyModifiedBuffers()
+{
+ BufferList::iterator bit = theBufferList().begin();
+ BufferList::iterator const bend = theBufferList().end();
+ for (; bit != bend; ++bit) {
+ if ((*bit)->fileName().exists()
+ && (*bit)->isExternallyModified(Buffer::checksum_method)) {
+ docstring text = bformat(_("Document \n%1$s\n has been externally modified."
+ " Reload now? Any local changes will be lost."),
+ from_utf8((*bit)->absFileName()));
+ int const ret = Alert::prompt(_("Reload externally changed document?"),
+ text, 0, 1, _("&Reload"), _("&Cancel"));
+ if (!ret)
+ (*bit)->reload();
+ }
+ }
+}
+
+
+//FIXME use a DispatchResult object to transmit messages
+void GuiView::dispatchVC(FuncRequest const & cmd)
+{
+ // message for statusbar
+ string msg;
+ Buffer * buffer = documentBufferView()
+ ? &(documentBufferView()->buffer()) : 0;
+
+ switch (cmd.action) {
+ case LFUN_VC_REGISTER:
+ if (!buffer || !ensureBufferClean(buffer))
+ break;
+ if (!buffer->lyxvc().inUse()) {
+ if (buffer->lyxvc().registrer())
+ reloadBuffer();
+ }
+ break;
+
+ case LFUN_VC_CHECK_IN:
+ if (!buffer || !ensureBufferClean(buffer))
+ break;
+ if (buffer->lyxvc().inUse() && !buffer->isReadonly()) {
+ msg = buffer->lyxvc().checkIn();
+ if (!msg.empty())
+ reloadBuffer();
+ }
+ break;
+
+ case LFUN_VC_CHECK_OUT:
+ if (!buffer || !ensureBufferClean(buffer))
+ break;
+ if (buffer->lyxvc().inUse()) {
+ msg = buffer->lyxvc().checkOut();
+ reloadBuffer();
+ }
+ break;
+
+ case LFUN_VC_LOCKING_TOGGLE:
+ LASSERT(buffer, return);
+ if (!ensureBufferClean(buffer) || buffer->isReadonly())
+ break;
+ if (buffer->lyxvc().inUse()) {
+ string res = buffer->lyxvc().lockingToggle();
+ if (res.empty()) {
+ frontend::Alert::error(_("Revision control error."),
+ _("Error when setting the locking property."));
+ } else {
+ msg = res;
+ reloadBuffer();
+ }
+ }
+ break;
+
+ case LFUN_VC_REVERT:
+ LASSERT(buffer, return);
+ buffer->lyxvc().revert();
+ reloadBuffer();
+ break;
+
+ case LFUN_VC_UNDO_LAST:
+ LASSERT(buffer, return);
+ buffer->lyxvc().undoLast();
+ reloadBuffer();
+ break;
+
+ case LFUN_VC_REPO_UPDATE:
+ LASSERT(buffer, return);
+ if (ensureBufferClean(buffer)) {
+ msg = buffer->lyxvc().repoUpdate();
+ checkExternallyModifiedBuffers();
+ }
+ break;
+
+ case LFUN_VC_COMMAND: {
+ string flag = cmd.getArg(0);
+ if (buffer && contains(flag, 'R') && !ensureBufferClean(buffer))
+ break;
+ docstring message;
+ if (contains(flag, 'M')) {
+ if (!Alert::askForText(message, _("LyX VC: Log Message")))
+ break;
+ }
+ string path = cmd.getArg(1);
+ if (contains(path, "$$p") && buffer)
+ path = subst(path, "$$p", buffer->filePath());
+ LYXERR(Debug::LYXVC, "Directory: " << path);
+ FileName pp(path);
+ if (!pp.isReadableDirectory()) {
+ lyxerr << _("Directory is not accessible.") << endl;
+ break;
+ }
+ support::PathChanger p(pp);
+
+ string command = cmd.getArg(2);
+ if (command.empty())
+ break;
+ if (buffer) {
+ command = subst(command, "$$i", buffer->absFileName());
+ command = subst(command, "$$p", buffer->filePath());
+ }
+ command = subst(command, "$$m", to_utf8(message));
+ LYXERR(Debug::LYXVC, "Command: " << command);
+ Systemcall one;
+ one.startscript(Systemcall::Wait, command);
+
+ if (!buffer)
+ break;
+ if (contains(flag, 'I'))
+ buffer->markDirty();
+ if (contains(flag, 'R'))
+ reloadBuffer();
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!msg.empty())
+ message(from_utf8(msg));
+}
+
+
+void GuiView::openChildDocument(string const & fname)
+{
+ LASSERT(documentBufferView(), return);
+ Buffer & buffer = documentBufferView()->buffer();
+ FileName const filename = support::makeAbsPath(fname, buffer.filePath());
+ documentBufferView()->saveBookmark(false);
+ Buffer * child = 0;
+ bool parsed = false;
+ if (theBufferList().exists(filename)) {
+ child = theBufferList().getBuffer(filename);
+ } else {
+ message(bformat(_("Opening child document %1$s..."),
+ makeDisplayPath(filename.absFilename())));
+ child = loadDocument(filename, false);
+ parsed = true;
+ }
+ if (!child)
+ return;
+
+ // Set the parent name of the child document.
+ // This makes insertion of citations and references in the child work,
+ // when the target is in the parent or another child document.
+ child->setParent(&buffer);
+ child->masterBuffer()->updateLabels();
+ setBuffer(child);
+ if (parsed)
+ child->errors("Parse");
+}
+
+
+bool GuiView::goToFileRow(string const & argument)
+{
+ string file_name;
+ int row;
+ size_t i = argument.find_last_of(' ');
+ if (i != string::npos) {
+ file_name = os::internal_path(trim(argument.substr(0, i)));
+ istringstream is(argument.substr(i + 1));
+ is >> row;
+ if (is.fail())
+ i = string::npos;
+ }
+ if (i == string::npos) {
+ LYXERR0("Wrong argument: " << argument);
+ return false;
+ }
+ Buffer * buf = 0;
+ string const abstmp = package().temp_dir().absFilename();
+ string const realtmp = package().temp_dir().realPath();
+ // We have to use os::path_prefix_is() here, instead of
+ // simply prefixIs(), because the file name comes from
+ // an external application and may need case adjustment.
+ if (os::path_prefix_is(file_name, abstmp, os::CASE_ADJUSTED)
+ || os::path_prefix_is(file_name, realtmp, os::CASE_ADJUSTED)) {
+ // Needed by inverse dvi search. If it is a file
+ // in tmpdir, call the apropriated function.
+ // If tmpdir is a symlink, we may have the real
+ // path passed back, so we correct for that.
+ if (!prefixIs(file_name, abstmp))
+ file_name = subst(file_name, realtmp, abstmp);
+ buf = theBufferList().getBufferFromTmp(file_name);
+ } else {
+ // Must replace extension of the file to be .lyx
+ // and get full path
+ FileName const s = fileSearch(string(),
+ support::changeExtension(file_name, ".lyx"), "lyx");
+ // Either change buffer or load the file
+ if (theBufferList().exists(s))
+ buf = theBufferList().getBuffer(s);
+ else if (s.exists()) {
+ buf = loadDocument(s);
+ buf->updateLabels();
+ buf->errors("Parse");
+ } else {
+ message(bformat(
+ _("File does not exist: %1$s"),
+ makeDisplayPath(file_name)));
+ return false;
+ }
+ }
+ setBuffer(buf);
+ documentBufferView()->setCursorFromRow(row);
+ return true;
+}
+
+
+#if (QT_VERSION >= 0x040400)
+static docstring exportAndDestroy(Buffer * buffer, string const & format)