commit 83fded8feae6d3a7f4c11689ccef41de979b569a
Author: Richard Heck <rgh...@lyx.org>
Date:   Mon Feb 19 22:43:44 2018 -0500

    Fix some problems with background cancellation.
    
    The problem was that, if we killed export when some graphic was
    being converted, or some external template was being handled, it
    would only cancel that process, and then it would just continue.
    To deal with that, we need to do a few things:
    1. Modify the return values for some of the Converters routines,
       and similarly the routines for external templates,  so we can
       tell when something has been canceled.
    2. Throw an exception from InsetGraphics or InsetExternal when this
       has happened during export, but ONLY when the Buffer is a clone.
       We shouldn't be able to 'cancel' export when we're, say, generating
       code for the preview pane, but this keeps us on the safe side..
    The exception then has to be caught, obviously, back in the export
    routines in Buffer.
    
    Probably Coverity will be unhappy about something here, but I'll
    deal with that problem as it arises.
---
 src/Buffer.cpp                 |  117 +++++++++++++++++++++++++++-------------
 src/Buffer.h                   |   13 +++--
 src/Converter.cpp              |   68 ++++++++++++-----------
 src/Converter.h                |   22 ++++++--
 src/frontends/qt4/GuiView.cpp  |    7 ++-
 src/insets/ExternalSupport.cpp |   55 +++++++++++--------
 src/insets/ExternalSupport.h   |    9 +++-
 src/insets/InsetExternal.cpp   |   56 ++++++++++++++-----
 src/insets/InsetGraphics.cpp   |   19 +++++--
 src/insets/InsetInclude.cpp    |   25 ++++++---
 10 files changed, 260 insertions(+), 131 deletions(-)

diff --git a/src/Buffer.cpp b/src/Buffer.cpp
index 867c4c5..61f2bfc 100644
--- a/src/Buffer.cpp
+++ b/src/Buffer.cpp
@@ -1102,7 +1102,9 @@ bool Buffer::importFile(string const & format, FileName 
const & name, ErrorList
                return false;
 
        FileName const lyx = tempFileName("Buffer_importFileXXXXXX.lyx");
-       if (theConverters().convert(0, name, lyx, name, format, "lyx", 
errorList)) {
+       Converters::RetVal const retval =
+           theConverters().convert(0, name, lyx, name, format, "lyx", 
errorList);
+       if (retval == Converters::SUCCESS) {
                bool const success = readFile(lyx) == ReadSuccess;
                removeTempFile(lyx);
                return success;
@@ -1658,7 +1660,7 @@ bool Buffer::write(ostream & ofs) const
 }
 
 
-bool Buffer::makeLaTeXFile(FileName const & fname,
+Buffer::ExportStatus Buffer::makeLaTeXFile(FileName const & fname,
                           string const & original_path,
                           OutputParams const & runparams_in,
                           OutputWhat output) const
@@ -1682,14 +1684,14 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
                Alert::error(_("Iconv software exception Detected"), 
bformat(_("Please "
                        "verify that the support software for your encoding 
(%1$s) is "
                        "properly installed"), from_ascii(encoding)));
-               return false;
+               return ExportError;
        }
        if (!openFileWrite(ofs, fname))
-               return false;
+               return ExportError;
 
        ErrorList & errorList = d->errorLists["Export"];
        errorList.clear();
-       bool failed_export = false;
+       ExportStatus status = ExportSuccess;
        otexstream os(ofs);
 
        // make sure we are ready to export
@@ -1699,8 +1701,11 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
        updateBuffer();
        updateMacroInstances(OutputUpdate);
 
+       ExportStatus retval;
        try {
-               writeLaTeXSource(os, original_path, runparams, output);
+               retval = writeLaTeXSource(os, original_path, runparams, output);
+               if (retval == ExportKilled)
+                       return ExportKilled;
        }
        catch (EncodingException const & e) {
                docstring const failed(1, e.failed_char);
@@ -1723,18 +1728,18 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
                                        "Changing the document encoding to utf8 
could help."),
                                                      {e.par_id, e.pos}, 
{e.par_id, e.pos + 1}));
                }
-               failed_export = true;
+               status = ExportError;
        }
        catch (iconv_codecvt_facet_exception const & e) {
                errorList.push_back(ErrorItem(_("iconv conversion failed"),
                                              _(e.what())));
-               failed_export = true;
+               status = ExportError;
        }
        catch (exception const & e) {
                errorList.push_back(ErrorItem(_("conversion failed"),
                                              _(e.what())));
                lyxerr << e.what() << endl;
-               failed_export = true;
+               status = ExportError;
        }
        catch (...) {
                lyxerr << "Caught some really weird exception..." << endl;
@@ -1745,7 +1750,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
 
        ofs.close();
        if (ofs.fail()) {
-               failed_export = true;
+               status = ExportError;
                lyxerr << "File '" << fname << "' was not closed properly." << 
endl;
        }
 
@@ -1753,11 +1758,11 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
                errorList.clear();
        else
                errors("Export");
-       return !failed_export;
+       return status;
 }
 
 
-void Buffer::writeLaTeXSource(otexstream & os,
+Buffer::ExportStatus Buffer::writeLaTeXSource(otexstream & os,
                           string const & original_path,
                           OutputParams const & runparams_in,
                           OutputWhat output) const
@@ -1951,7 +1956,7 @@ void Buffer::writeLaTeXSource(otexstream & os,
                        // Restore the parenthood if needed
                        if (!runparams.is_child)
                                d->ignore_parent = false;
-                       return;
+                       return ExportSuccess;
                }
 
                // make the body.
@@ -1974,7 +1979,10 @@ void Buffer::writeLaTeXSource(otexstream & os,
        LYXERR(Debug::INFO, "preamble finished, now the body.");
 
        // the real stuff
-       latexParagraphs(*this, text(), os, runparams);
+       try {
+               latexParagraphs(*this, text(), os, runparams);
+       }
+       catch (ConversionException const &) { return ExportKilled; }
 
        // Restore the parenthood if needed
        if (!runparams.is_child)
@@ -1993,10 +2001,11 @@ void Buffer::writeLaTeXSource(otexstream & os,
 
        LYXERR(Debug::INFO, "Finished making LaTeX file.");
        LYXERR(Debug::INFO, "Row count was " << os.texrow().rows() - 1 << '.');
+       return ExportSuccess;
 }
 
 
-void Buffer::makeDocBookFile(FileName const & fname,
+Buffer::ExportStatus Buffer::makeDocBookFile(FileName const & fname,
                              OutputParams const & runparams,
                              OutputWhat output) const
 {
@@ -2004,22 +2013,26 @@ void Buffer::makeDocBookFile(FileName const & fname,
 
        ofdocstream ofs;
        if (!openFileWrite(ofs, fname))
-               return;
+               return ExportError;
 
        // make sure we are ready to export
        // this needs to be done before we validate
        updateBuffer();
        updateMacroInstances(OutputUpdate);
 
-       writeDocBookSource(ofs, fname.absFileName(), runparams, output);
+       ExportStatus const retval =
+               writeDocBookSource(ofs, fname.absFileName(), runparams, output);
+       if (retval == ExportKilled)
+               return ExportKilled;
 
        ofs.close();
        if (ofs.fail())
                lyxerr << "File '" << fname << "' was not closed properly." << 
endl;
+       return ExportSuccess;
 }
 
 
-void Buffer::writeDocBookSource(odocstream & os, string const & fname,
+Buffer::ExportStatus Buffer::writeDocBookSource(odocstream & os, string const 
& fname,
                             OutputParams const & runparams,
                             OutputWhat output) const
 {
@@ -2093,35 +2106,42 @@ void Buffer::writeDocBookSource(odocstream & os, string 
const & fname,
 
                sgml::openTag(os, top);
                os << '\n';
-               docbookParagraphs(text(), *this, os, runparams);
+               try {
+                       docbookParagraphs(text(), *this, os, runparams);
+               }
+               catch (ConversionException const &) { return ExportKilled; }
                sgml::closeTag(os, top_element);
        }
+       return ExportSuccess;
 }
 
 
-void Buffer::makeLyXHTMLFile(FileName const & fname,
+Buffer::ExportStatus Buffer::makeLyXHTMLFile(FileName const & fname,
                              OutputParams const & runparams) const
 {
        LYXERR(Debug::LATEX, "makeLyXHTMLFile...");
 
        ofdocstream ofs;
        if (!openFileWrite(ofs, fname))
-               return;
+               return ExportError;
 
        // make sure we are ready to export
        // this has to be done before we validate
        updateBuffer(UpdateMaster, OutputUpdate);
        updateMacroInstances(OutputUpdate);
 
-       writeLyXHTMLSource(ofs, runparams, FullSource);
+       ExportStatus const retval = writeLyXHTMLSource(ofs, runparams, 
FullSource);
+       if (retval == ExportKilled)
+               return retval;
 
        ofs.close();
        if (ofs.fail())
                lyxerr << "File '" << fname << "' was not closed properly." << 
endl;
+       return retval;
 }
 
 
-void Buffer::writeLyXHTMLSource(odocstream & os,
+Buffer::ExportStatus Buffer::writeLyXHTMLSource(odocstream & os,
                             OutputParams const & runparams,
                             OutputWhat output) const
 {
@@ -2222,13 +2242,18 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
                if (output != IncludedFile)
                        // if we're an included file, the counters are in the 
master.
                        params().documentClass().counters().reset();
-               xhtmlParagraphs(text(), *this, xs, runparams);
+               try {
+                       xhtmlParagraphs(text(), *this, xs, runparams);
+               }
+               catch (ConversionException const &) { return ExportKilled; }
                if (output_body_tag)
                        os << "</body>\n";
        }
 
        if (output_preamble)
                os << "</html>\n";
+
+       return ExportSuccess;
 }
 
 
@@ -2251,7 +2276,12 @@ int Buffer::runChktex()
        runparams.flavor = OutputParams::LATEX;
        runparams.nice = false;
        runparams.linelen = lyxrc.plaintext_linelen;
-       makeLaTeXFile(FileName(name), org_path, runparams);
+       ExportStatus const retval =
+               makeLaTeXFile(FileName(name), org_path, runparams);
+       if (retval != ExportSuccess) {
+               // error code on failure
+               return -1;
+       }
 
        TeXErrors terr;
        Chktex chktex(lyxrc.chktex_command, onlyFileName(name), filePath());
@@ -4297,28 +4327,36 @@ Buffer::ExportStatus Buffer::doExport(string const & 
target, bool put_in_tempdir
        // Plain text backend
        if (backend_format == "text") {
                runparams.flavor = OutputParams::TEXT;
-               writePlaintextFile(*this, FileName(filename), runparams);
+               try {
+                       writePlaintextFile(*this, FileName(filename), 
runparams);
+               }
+               catch (ConversionException const &) { return ExportCancel; }
        }
        // HTML backend
        else if (backend_format == "xhtml") {
                runparams.flavor = OutputParams::HTML;
                setMathFlavor(runparams);
-               makeLyXHTMLFile(FileName(filename), runparams);
+               if (makeLyXHTMLFile(FileName(filename), runparams) == 
ExportKilled)
+                       return ExportKilled;
        } else if (backend_format == "lyx")
                writeFile(FileName(filename));
        // Docbook backend
        else if (params().isDocBook()) {
                runparams.nice = !put_in_tempdir;
-               makeDocBookFile(FileName(filename), runparams);
+               if (makeDocBookFile(FileName(filename), runparams) == 
ExportKilled)
+                       return ExportKilled;
        }
        // LaTeX backend
        else if (backend_format == format || need_nice_file) {
                runparams.nice = true;
-               bool const success = makeLaTeXFile(FileName(filename), 
string(), runparams);
+               ExportStatus const retval =
+                       makeLaTeXFile(FileName(filename), string(), runparams);
+               if (retval == ExportKilled)
+                       return ExportKilled;
                if (d->cloned_buffer_)
                        d->cloned_buffer_->d->errorLists["Export"] = 
d->errorLists["Export"];
-               if (!success)
-                       return ExportError;
+               if (retval != ExportSuccess)
+                       return retval;
        } else if (!lyxrc.tex_allows_spaces
                   && contains(filePath(), ' ')) {
                Alert::error(_("File name error"),
@@ -4326,11 +4364,13 @@ Buffer::ExportStatus Buffer::doExport(string const & 
target, bool put_in_tempdir
                return ExportTexPathHasSpaces;
        } else {
                runparams.nice = false;
-               bool const success = makeLaTeXFile(
-                       FileName(filename), filePath(), runparams);
+               ExportStatus const retval =
+                       makeLaTeXFile(FileName(filename), filePath(), 
runparams);
+               if (retval == ExportKilled)
+                       return ExportKilled;
                if (d->cloned_buffer_)
                        d->cloned_buffer_->d->errorLists["Export"] = 
d->errorLists["Export"];
-               if (!success)
+               if (retval != ExportSuccess)
                        return ExportError;
        }
 
@@ -4339,9 +4379,12 @@ Buffer::ExportStatus Buffer::doExport(string const & 
target, bool put_in_tempdir
        ErrorList & error_list = d->errorLists[error_type];
        string const ext = theFormats().extension(format);
        FileName const tmp_result_file(changeExtension(filename, ext));
-       bool const success = converters.convert(this, FileName(filename),
-               tmp_result_file, FileName(absFileName()), backend_format, 
format,
-               error_list);
+       Converters::RetVal const retval = 
+               converters.convert(this, FileName(filename), tmp_result_file, 
+               FileName(absFileName()), backend_format, format, error_list);
+       if (retval == Converters::KILLED)
+               return ExportCancel;
+       bool success = (retval == Converters::SUCCESS);
 
        // Emit the signal to show the error list or copy it back to the
        // cloned Buffer so that it can be emitted afterwards.
diff --git a/src/Buffer.h b/src/Buffer.h
index b5a71a2..9f40e74 100644
--- a/src/Buffer.h
+++ b/src/Buffer.h
@@ -133,6 +133,7 @@ public:
                // export
                ExportSuccess,
                ExportCancel,
+               ExportKilled,
                ExportError,
                ExportNoPathToFormat,
                ExportTexPathHasSpaces,
@@ -297,7 +298,7 @@ public:
        };
 
        /// Just a wrapper for writeLaTeXSource, first creating the ofstream.
-       bool makeLaTeXFile(support::FileName const & filename,
+       ExportStatus makeLaTeXFile(support::FileName const & filename,
                           std::string const & original_path,
                           OutputParams const &,
                           OutputWhat output = FullSource) const;
@@ -323,23 +324,23 @@ public:
            ofs.close();
            \endcode
         */
-       void writeLaTeXSource(otexstream & os,
+       ExportStatus writeLaTeXSource(otexstream & os,
                           std::string const & original_path,
                           OutputParams const &,
                           OutputWhat output = FullSource) const;
        ///
-       void makeDocBookFile(support::FileName const & filename,
+       ExportStatus makeDocBookFile(support::FileName const & filename,
                             OutputParams const & runparams_in,
                             OutputWhat output = FullSource) const;
        ///
-       void writeDocBookSource(odocstream & os, std::string const & filename,
+       ExportStatus writeDocBookSource(odocstream & os, std::string const & 
filename,
                             OutputParams const & runparams_in,
                             OutputWhat output = FullSource) const;
        ///
-       void makeLyXHTMLFile(support::FileName const & filename,
+       ExportStatus makeLyXHTMLFile(support::FileName const & filename,
                             OutputParams const & runparams_in) const;
        ///
-       void writeLyXHTMLSource(odocstream & os,
+       ExportStatus writeLyXHTMLSource(odocstream & os,
                             OutputParams const & runparams_in,
                             OutputWhat output = FullSource) const;
        /// returns the main language for the buffer (document)
diff --git a/src/Converter.cpp b/src/Converter.cpp
index 37977b4..e1a47db 100644
--- a/src/Converter.cpp
+++ b/src/Converter.cpp
@@ -398,18 +398,20 @@ bool Converters::checkAuth(Converter const & conv, string 
const & doc_fname,
 }
 
 
-bool Converters::convert(Buffer const * buffer,
+Converters::RetVal Converters::convert(Buffer const * buffer,
                         FileName const & from_file, FileName const & to_file,
                         FileName const & orig_from,
                         string const & from_format, string const & to_format,
                         ErrorList & errorList, int conversionflags)
 {
        if (from_format == to_format)
-               return move(from_format, from_file, to_file, false);
+               return move(from_format, from_file, to_file, false) ?
+                     SUCCESS : FAILURE;
 
        if ((conversionflags & try_cache) &&
            ConverterCache::get().inCache(orig_from, to_format))
-               return ConverterCache::get().copy(orig_from, to_format, 
to_file);
+               return ConverterCache::get().copy(orig_from, to_format, 
to_file) ?
+                     SUCCESS : FAILURE;
 
        Graph::EdgePath edgepath = getPath(from_format, to_format);
        if (edgepath.empty()) {
@@ -439,22 +441,22 @@ bool Converters::convert(Buffer const * buffer,
                        if (exitval == Systemcall::KILLED) {
                                frontend::Alert::warning(
                                        _("Converter killed"),
-                                       bformat(_("The running converter\n 
%1$s\nwas killed by the user."), 
+                                       bformat(_("The following converter was 
killed by the user.\n %1$s\n"),
                                                from_utf8(command)));
-                               return false;
+                               return KILLED;
                        }
                        if (to_file.isReadableFile()) {
                                if (conversionflags & try_cache)
                                        ConverterCache::get().add(orig_from,
                                                        to_format, to_file);
-                               return true;
+                               return SUCCESS;
                        }
                }
 
                // only warn once per session and per file type
                static std::map<string, string> warned;
                if (warned.find(from_format) != warned.end() && 
warned.find(from_format)->second == to_format) {
-                       return false;
+                       return FAILURE;
                }
                warned.insert(make_pair(from_format, to_format));
 
@@ -463,7 +465,7 @@ bool Converters::convert(Buffer const * buffer,
                                                    "format files to %2$s.\n"
                                                    "Define a converter in the 
preferences."),
                                                        
from_ascii(from_format), from_ascii(to_format)));
-               return false;
+               return FAILURE;
        }
 
        // buffer is only invalid for importing, and then runparams is not
@@ -574,7 +576,7 @@ bool Converters::convert(Buffer const * buffer,
 
                if (!checkAuth(conv, buffer ? buffer->absFileName() : string(),
                               buffer && buffer->params().shell_escape))
-                       return false;
+                       return FAILURE;
 
                if (conv.latex()) {
                        // We are not importing, we have a buffer
@@ -590,8 +592,9 @@ bool Converters::convert(Buffer const * buffer,
                        LYXERR(Debug::FILES, "Running " << command);
                        // FIXME KILLED
                        // Check changed return value here.
-                       if (!runLaTeX(*buffer, command, runparams, errorList))
-                               return false;
+                       RetVal const retval = runLaTeX(*buffer, command, 
runparams, errorList);
+                               if (retval != SUCCESS)
+                                       return retval;
                } else {
                        if (conv.need_aux() && !run_latex) {
                                // We are not importing, we have a buffer
@@ -620,9 +623,9 @@ bool Converters::convert(Buffer const * buffer,
                                                << " to update aux file");
                                        // FIXME KILLED
                                        // Check changed return value here.
-                                       if (!runLaTeX(*buffer, command,
-                                                     runparams, errorList))
-                                               return false;
+                                       RetVal const retval = runLaTeX(*buffer, 
command, runparams, errorList);
+                                               if (retval != SUCCESS)
+                                                       return retval;
                                }
                        }
 
@@ -680,9 +683,9 @@ bool Converters::convert(Buffer const * buffer,
                                if (res == Systemcall::KILLED) {
                                        frontend::Alert::warning(
                                                _("Converter killed"),
-                                               bformat(_("The running 
converter\n %1$s\nwas killed by the user."), 
+                                               bformat(_("The following 
converter was killed by the user.\n %1$s\n"), 
                                                        from_utf8(command)));
-                                       return false;
+                                       return KILLED;
                                }
                                
                                if (!real_outfile.empty()) {
@@ -709,12 +712,12 @@ bool Converters::convert(Buffer const * buffer,
                                        if (res == Systemcall::KILLED) {
                                                frontend::Alert::warning(
                                                        _("Converter killed"),
-                                                       bformat(_("The running 
converter\n %1$s\nwas killed by the user."), 
+                                                       bformat(_("The 
following converter was killed by the user.\n %1$s\n"), 
                                                                
from_utf8(command)));
-                                               return false;
+                                               return KILLED;
                                        }
                                        if (!scanLog(*buffer, command, 
makeAbsPath(logfile, path), errorList))
-                                               return false;
+                                               return FAILURE;
                                }
                        }
 
@@ -723,11 +726,15 @@ bool Converters::convert(Buffer const * buffer,
                                        Alert::information(_("Process Killed"),
                                                bformat(_("The conversion 
process was killed while running:\n%1$s"),
                                                        
wrapParas(from_utf8(command))));
-                               } else if (res == Systemcall::TIMEOUT) {
+                                       return KILLED;
+                               } 
+                               if (res == Systemcall::TIMEOUT) {
                                        Alert::information(_("Process Timed 
Out"),
                                                bformat(_("The conversion 
process:\n%1$s\ntimed out before completing."),
                                                        
wrapParas(from_utf8(command))));
-                               } else if (conv.to() == "program") {
+                                       return KILLED;
+                               } 
+                               if (conv.to() == "program") {
                                        Alert::error(_("Build errors"),
                                                _("There were errors during the 
build process."));
                                } else {
@@ -737,14 +744,14 @@ bool Converters::convert(Buffer const * buffer,
                                                bformat(_("An error occurred 
while running:\n%1$s"),
                                                wrapParas(from_utf8(command))));
                                }
-                               return false;
+                               return FAILURE;
                        }
                }
        }
 
        Converter const & conv = converterlist_[edgepath.back()];
        if (conv.To()->dummy())
-               return true;
+               return SUCCESS;
 
        if (!conv.result_dir().empty()) {
                // The converter has put the file(s) in a directory.
@@ -759,14 +766,14 @@ bool Converters::convert(Buffer const * buffer,
                                Alert::error(_("Cannot convert file"),
                                        bformat(_("Could not move a temporary 
directory from %1$s to %2$s."),
                                                from_utf8(from), 
from_utf8(to)));
-                               return false;
+                               return FAILURE;
                        }
                }
-               return true;
+               return SUCCESS;
        } else {
                if (conversionflags & try_cache)
                        ConverterCache::get().add(orig_from, to_format, 
outfile);
-               return move(conv.to(), outfile, to_file, conv.latex());
+               return move(conv.to(), outfile, to_file, conv.latex()) ? 
SUCCESS : FAILURE;
        }
 }
 
@@ -840,9 +847,7 @@ bool Converters::scanLog(Buffer const & buffer, string 
const & /*command*/,
 }
 
 
-// FIXME KILL
-// Probably need to return an INT here
-bool Converters::runLaTeX(Buffer const & buffer, string const & command,
+Converters::RetVal Converters::runLaTeX(Buffer const & buffer, string const & 
command,
                          OutputParams const & runparams, ErrorList & errorList)
 {
        buffer.setBusy(true);
@@ -865,7 +870,7 @@ bool Converters::runLaTeX(Buffer const & buffer, string 
const & command,
        if (result == Systemcall::KILLED) {
                Alert::error(_("Export canceled"),
                        _("The export process was terminated by the user."));
-               return result;
+               return KILLED;
        }
 
        if (result & LaTeX::ERRORS)
@@ -894,7 +899,6 @@ bool Converters::runLaTeX(Buffer const & buffer, string 
const & command,
                               _("No output file was generated."));
        }
 
-
        buffer.setBusy(false);
 
        int const ERROR_MASK =
@@ -902,7 +906,7 @@ bool Converters::runLaTeX(Buffer const & buffer, string 
const & command,
                        LaTeX::ERRORS |
                        LaTeX::NO_OUTPUT;
 
-       return (result & ERROR_MASK) == 0;
+       return (result & ERROR_MASK) == 0 ? SUCCESS : FAILURE;
 }
 
 
diff --git a/src/Converter.h b/src/Converter.h
index e144ca2..0031d02 100644
--- a/src/Converter.h
+++ b/src/Converter.h
@@ -30,9 +30,17 @@ class ErrorList;
 class Format;
 class Formats;
 
-typedef std::vector<Format const *> FormatList;
+class ConversionException : public std::exception {
+public:
+       ConversionException() {}
+       virtual ~ConversionException() throw() {}
+       virtual const char * what() const throw() 
+               { return "Exception caught in conversion routine!"; }
+};
 
 
+typedef std::vector<Format const *> FormatList;
+
 ///
 class Converter {
 public:
@@ -128,7 +136,13 @@ public:
        typedef std::vector<Converter> ConverterList;
        ///
        typedef ConverterList::const_iterator const_iterator;
-
+       /// Return values for converter runs
+       enum RetVal {
+               SUCCESS = 0,
+               FAILURE = 1,
+               KILLED  = 1000
+       };
+       
        ///
        Converter const & get(int i) const { return converterlist_[i]; }
        ///
@@ -175,7 +189,7 @@ public:
                try_cache = 1 << 1
        };
        ///
-       bool convert(Buffer const * buffer,
+       RetVal convert(Buffer const * buffer,
                     support::FileName const & from_file, support::FileName 
const & to_file,
                     support::FileName const & orig_from,
                     std::string const & from_format, std::string const & 
to_format,
@@ -216,7 +230,7 @@ private:
        bool scanLog(Buffer const & buffer, std::string const & command,
                     support::FileName const & filename, ErrorList & errorList);
        ///
-       bool runLaTeX(Buffer const & buffer, std::string const & command,
+       RetVal runLaTeX(Buffer const & buffer, std::string const & command,
                      OutputParams const &, ErrorList & errorList);
        ///
        ConverterList converterlist_;
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index 5cb6eea..527f410 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -701,6 +701,9 @@ static void handleExportStatus(GuiView * view, 
Buffer::ExportStatus status,
        case Buffer::PreviewError:
                msg = bformat(_("Error while previewing format: %1$s"), fmt);
                break;
+       case Buffer::ExportKilled:
+               msg = bformat(_("Conversion cancelled while previewing format: 
%1$s"), fmt);
+               break;
        }
        view->message(msg);
 }
@@ -2369,8 +2372,8 @@ static bool import(GuiView * lv, FileName const & 
filename,
                        string const tofile =
                                support::changeExtension(filename.absFileName(),
                                theFormats().extension(*it));
-                       if (!theConverters().convert(0, filename, 
FileName(tofile),
-                               filename, format, *it, errorList))
+                       if (theConverters().convert(0, filename, 
FileName(tofile),
+                               filename, format, *it, errorList) != 
Converters::SUCCESS)
                                return false;
                        loader_format = *it;
                        break;
diff --git a/src/insets/ExternalSupport.cpp b/src/insets/ExternalSupport.cpp
index 3a214ca..d333d22 100644
--- a/src/insets/ExternalSupport.cpp
+++ b/src/insets/ExternalSupport.cpp
@@ -213,7 +213,7 @@ namespace {
     If \p external_in_tmpdir == true, then the generated file is
     placed in the buffer's temporary directory.
 */
-void updateExternal(InsetExternalParams const & params,
+RetVal updateExternal(InsetExternalParams const & params,
                    string const & format,
                    Buffer const & buffer,
                    ExportData & exportdata,
@@ -222,38 +222,38 @@ void updateExternal(InsetExternalParams const & params,
 {
        Template const * const et_ptr = getTemplatePtr(params);
        if (!et_ptr)
-               return; // FAILURE
+               return FAILURE;
        Template const & et = *et_ptr;
 
        if (!et.automaticProduction)
-               return; // NOT_NEEDED
+               return NOT_NEEDED;
 
        Template::Formats::const_iterator cit = et.formats.find(format);
        if (cit == et.formats.end())
-               return; // FAILURE
+               return FAILURE;
 
        Template::Format const & outputFormat = cit->second;
        if (outputFormat.updateResult.empty())
-               return; // NOT_NEEDED
+               return NOT_NEEDED;
 
        string from_format = et.inputFormat;
        if (from_format.empty())
-               return; // NOT_NEEDED
+               return NOT_NEEDED;
 
        if (from_format == "*") {
                if (params.filename.empty())
-                       return; // NOT_NEEDED
+                       return NOT_NEEDED;
 
                // Try and ascertain the file format from its contents.
                from_format = theFormats().getFormatFromFile(params.filename);
                if (from_format.empty())
-                       return; // FAILURE
+                       return FAILURE;
        }
 
        string const to_format = doSubstitution(params, buffer,
                outputFormat.updateFormat, false, external_in_tmpdir, FORMATS);
        if (to_format.empty())
-               return; // NOT_NEEDED
+               return NOT_NEEDED;
 
        // The master buffer. This is useful when there are multiple levels
        // of include files
@@ -274,7 +274,7 @@ void updateExternal(InsetExternalParams const & params,
                        if (!mover.copy(params.filename, temp_file)) {
                                LYXERR(Debug::EXTERNAL, 
"external::updateExternal. "
                                        << "Unable to copy " << params.filename 
<< " to " << temp_file);
-                               return; // FAILURE
+                               return FAILURE;
                        }
                }
        }
@@ -324,21 +324,26 @@ void updateExternal(InsetExternalParams const & params,
        // Yes if to_file does not exist or if from_file is newer than to_file
        // or if from_file is a directory (bug 9925)
        if (!isDir && compare_timestamps(temp_file, abs_to_file) < 0)
-               return; // SUCCESS
+               return SUCCESS;
 
        // FIXME (Abdel 12/08/06): Is there a need to show these errors?
        ErrorList el;
-       bool const success =
+       Converters::RetVal const success =
                theConverters().convert(&buffer, temp_file, abs_to_file,
                                   params.filename, from_format, to_format, el,
                                   Converters::try_default | 
Converters::try_cache);
-
-       if (!success) {
+       switch (success) {
+       case Converters::SUCCESS:
+               return SUCCESS;
+       case Converters::FAILURE:
                LYXERR(Debug::EXTERNAL, "external::updateExternal. "
                        << "Unable to convert from " << from_format << " to " 
<< to_format);
+                       return FAILURE;
+       case Converters::KILLED:
+               return KILLED;
        }
-
-       // return success
+       // squash warning
+       return SUCCESS;
 }
 
 
@@ -351,7 +356,7 @@ string const substituteOptions(InsetExternalParams const & 
params,
 } // namespace
 
 
-void writeExternal(InsetExternalParams const & params,
+RetVal writeExternal(InsetExternalParams const & params,
                   string const & format,
                   Buffer const & buffer, otexstream & os,
                   ExportData & exportdata,
@@ -360,19 +365,23 @@ void writeExternal(InsetExternalParams const & params,
 {
        Template const * const et_ptr = getTemplatePtr(params);
        if (!et_ptr)
-               return;
+               return FAILURE;
        Template const & et = *et_ptr;
 
        Template::Formats::const_iterator cit = et.formats.find(format);
        if (cit == et.formats.end()) {
                LYXERR(Debug::EXTERNAL, "External template format '" << format
                        << "' not specified in template " << 
params.templatename());
-               return;
+               return FAILURE;
        }
 
-       if (!dryrun || contains(cit->second.product, "$$Contents"))
-               updateExternal(params, format, buffer, exportdata,
-                              external_in_tmpdir, dryrun);
+       if (!dryrun || contains(cit->second.product, "$$Contents")) {
+               RetVal const success = 
+                       updateExternal(params, format, buffer, exportdata, 
+                               external_in_tmpdir, dryrun);
+               if (success == FAILURE || success == KILLED)
+                       return success;
+       }
 
        bool const use_latex_path = format == "LaTeX";
        string str = doSubstitution(params, buffer, cit->second.product,
@@ -401,7 +410,7 @@ void writeExternal(InsetExternalParams const & params,
        str = substituteOptions(params, str, format);
        // FIXME UNICODE
        os << from_utf8(str);
-       return;
+       return SUCCESS;
 }
 
 namespace {
diff --git a/src/insets/ExternalSupport.h b/src/insets/ExternalSupport.h
index cd42572..5c5619c 100644
--- a/src/insets/ExternalSupport.h
+++ b/src/insets/ExternalSupport.h
@@ -25,6 +25,13 @@ class otexstream;
 
 namespace external {
 
+enum RetVal {
+       SUCCESS,
+       NOT_NEEDED,
+       FAILURE,
+       KILLED
+};
+
 class Template;
 
 /// A shorthand, helper function
@@ -63,7 +70,7 @@ std::string const doSubstitution(InsetExternalParams const & 
params,
     If \p external_in_tmpdir == true, then the generated file is
     place in the buffer's temporary directory.
 */
-void writeExternal(InsetExternalParams const &,
+RetVal writeExternal(InsetExternalParams const &,
                   std::string const & format,
                   Buffer const &,
                   otexstream &,
diff --git a/src/insets/InsetExternal.cpp b/src/insets/InsetExternal.cpp
index 1f0f5f2..d3d3aaa 100644
--- a/src/insets/InsetExternal.cpp
+++ b/src/insets/InsetExternal.cpp
@@ -18,6 +18,7 @@
 
 #include "Buffer.h"
 #include "BufferView.h"
+#include "Converter.h"
 #include "Cursor.h"
 #include "DispatchResult.h"
 #include "Exporter.h"
@@ -728,19 +729,26 @@ void InsetExternal::latex(otexstream & os, OutputParams 
const & runparams) const
                        et.formats.find("PDFLaTeX");
 
                if (cit != et.formats.end()) {
-                       external::writeExternal(params_, "PDFLaTeX",
-                                               buffer(), os,
-                                               *(runparams.exportdata),
-                                               external_in_tmpdir,
-                                               dryrun);
+                       external::RetVal retval =
+                               external::writeExternal(params_, "PDFLaTeX", 
buffer(), os,
+                                   *(runparams.exportdata), 
external_in_tmpdir, dryrun);
+                       if (retval == external::KILLED) {
+                               LYXERR0("External template preparation 
killed.");
+                               if (buffer().isClone() && 
buffer().isExporting())
+                                       throw ConversionException();
+                       }
                        return;
                }
        }
 
-       external::writeExternal(params_, "LaTeX", buffer(), os,
-                               *(runparams.exportdata),
-                               external_in_tmpdir,
-                               dryrun);
+       external::RetVal retval =
+               external::writeExternal(params_, "LaTeX", buffer(), os,
+                   *(runparams.exportdata), external_in_tmpdir, dryrun);
+       if (retval == external::KILLED) {
+               LYXERR0("External template preparation killed.");
+               if (buffer().isClone() && buffer().isExporting())
+                       throw ConversionException();
+       }
 }
 
 
@@ -755,8 +763,14 @@ int InsetExternal::plaintext(odocstringstream & os,
        bool const dryrun = runparams.dryrun || runparams.inComment;
        otexstream ots(os);
        ots << '\n'; // output external material on a new line
-       external::writeExternal(params_, "Ascii", buffer(), ots,
-                               *(runparams.exportdata), external_in_tmpdir, 
dryrun);
+       external::RetVal retval =
+               external::writeExternal(params_, "Ascii", buffer(), ots,
+                   *(runparams.exportdata), external_in_tmpdir, dryrun);
+       if (retval == external::KILLED) {
+               LYXERR0("External template preparation killed.");
+               if (buffer().isClone() && buffer().isExporting())
+                       throw ConversionException();
+       }
        return PLAINTEXT_NEWLINE;
 }
 
@@ -768,8 +782,14 @@ int InsetExternal::docbook(odocstream & os,
        bool const dryrun = runparams.dryrun || runparams.inComment;
        odocstringstream ods;
        otexstream ots(ods);
-       external::writeExternal(params_, "DocBook", buffer(), ots,
-                               *(runparams.exportdata), external_in_tmpdir, 
dryrun);
+       external::RetVal retval =
+               external::writeExternal(params_, "DocBook", buffer(), ots,
+                   *(runparams.exportdata), external_in_tmpdir, dryrun);
+       if (retval == external::KILLED) {
+               LYXERR0("External template preparation killed.");
+               if (buffer().isClone() && buffer().isExporting())
+                       throw ConversionException();
+       }
        os << ods.str();
        return int(count(ods.str().begin(), ods.str().end(), '\n'));
 }
@@ -782,8 +802,14 @@ docstring InsetExternal::xhtml(XHTMLStream & xs,
        bool const dryrun = runparams.dryrun || runparams.inComment;
        odocstringstream ods;
        otexstream ots(ods);
-       external::writeExternal(params_, "XHTML", buffer(), ots,
-                                      *(runparams.exportdata), 
external_in_tmpdir, dryrun);
+       external::RetVal retval =
+               external::writeExternal(params_, "XHTML", buffer(), ots,
+                   *(runparams.exportdata), external_in_tmpdir, dryrun);
+       if (retval == external::KILLED) {
+               LYXERR0("External template preparation killed.");
+               if (buffer().isClone() && buffer().isExporting())
+                       throw ConversionException();
+       }
        xs << XHTMLStream::ESCAPE_NONE << ods.str();
        return docstring();
 }
diff --git a/src/insets/InsetGraphics.cpp b/src/insets/InsetGraphics.cpp
index 02a5630..a07296c 100644
--- a/src/insets/InsetGraphics.cpp
+++ b/src/insets/InsetGraphics.cpp
@@ -714,9 +714,15 @@ string InsetGraphics::prepareFile(OutputParams const & 
runparams) const
 
        // FIXME (Abdel 12/08/06): Is there a need to show these errors?
        ErrorList el;
-       if (theConverters().convert(&buffer(), temp_file, to_file, 
params().filename,
+       Converters::RetVal const rv = 
+           theConverters().convert(&buffer(), temp_file, to_file, 
params().filename,
                               from, to, el,
-                              Converters::try_default | 
Converters::try_cache)) {
+                              Converters::try_default | Converters::try_cache);
+       if (rv == Converters::KILLED) {
+               LYXERR0("Graphics preparation killed.");
+               if (buffer().isClone() && buffer().isExporting())
+                       throw ConversionException();
+       } else if (rv == Converters::SUCCESS) {
                runparams.exportdata->addExternalFile(tex_format,
                                to_file, output_to_file);
                runparams.exportdata->addExternalFile("dvi",
@@ -939,10 +945,15 @@ string InsetGraphics::prepareHTMLFile(OutputParams const 
& runparams) const
 
        // FIXME (Abdel 12/08/06): Is there a need to show these errors?
        ErrorList el;
-       bool const success =
+       Converters::RetVal const rv =
                theConverters().convert(&buffer(), temp_file, to_file, 
params().filename,
                        from, to, el, Converters::try_default | 
Converters::try_cache);
-       if (!success)
+       if (rv == Converters::KILLED) {
+               if (buffer().isClone() && buffer().isExporting())
+                       throw ConversionException();
+               return string();
+       }
+       if (rv != Converters::SUCCESS)
                return string();
        runparams.exportdata->addExternalFile("xhtml", to_file, output_to_file);
        return output_to_file;
diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp
index d7095cc..9a32d05 100644
--- a/src/insets/InsetInclude.cpp
+++ b/src/insets/InsetInclude.cpp
@@ -788,8 +788,16 @@ void InsetInclude::latex(otexstream & os, OutputParams 
const & runparams) const
                runparams.par_begin = 0;
                runparams.par_end = tmp->paragraphs().size();
                runparams.is_child = true;
-               if (!tmp->makeLaTeXFile(tmpwritefile, masterFileName(buffer()).
-                               onlyPath().absFileName(), runparams, 
Buffer::OnlyBody)) {
+               Buffer::ExportStatus retval =
+                       tmp->makeLaTeXFile(tmpwritefile, 
masterFileName(buffer()).
+                               onlyPath().absFileName(), runparams, 
Buffer::OnlyBody);
+               if (retval == Buffer::ExportKilled && buffer().isClone() &&
+                     buffer().isExporting()) {
+                 // We really shouldn't get here, I don't think.
+                 LYXERR0("No conversion exception?");
+                       throw ConversionException();
+               }
+               else if (retval != Buffer::ExportSuccess) {
                        if (!runparams.silent) {
                                docstring msg = bformat(_("Included file `%1$s' 
"
                                        "was not exported correctly.\n "
@@ -811,12 +819,15 @@ void InsetInclude::latex(otexstream & os, OutputParams 
const & runparams) const
                // If needed, use converters to produce a latex file from the 
child
                if (tmpwritefile != writefile) {
                        ErrorList el;
-                       bool const success =
+                       Converters::RetVal const retval =
                                theConverters().convert(tmp, tmpwritefile, 
writefile,
-                                                       included_file,
-                                                       inc_format, tex_format, 
el);
-
-                       if (!success && !runparams.silent) {
+                                   included_file, inc_format, tex_format, el);
+                       if (retval == Converters::KILLED && buffer().isClone() 
&&
+                           buffer().isExporting()) {
+                               // We really shouldn't get here, I don't think.
+                               LYXERR0("No conversion exception?");
+                               throw ConversionException();
+                       } else if (retval != Converters::SUCCESS && 
!runparams.silent) {
                                docstring msg = bformat(_("Included file `%1$s' 
"
                                                "was not exported correctly.\n "
                                                "LaTeX export is probably 
incomplete."),

Reply via email to