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.
This commit is contained in:
Richard Heck 2018-02-19 22:43:44 -05:00 committed by Richard Kimberly Heck
parent c97bc5f83a
commit 83fded8fea
10 changed files with 260 additions and 131 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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;
}

View File

@ -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_;

View File

@ -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;

View File

@ -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 {

View File

@ -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 &,

View File

@ -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();
}

View File

@ -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;

View File

@ -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."),