X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=8ca74103a232a48705cd0814cdb14ab1dba8a768;hb=c5cab5a8f7e1f0f3996c1655c45a0fb88576dd5f;hp=7024f974d5f4e93f98bd4dbde13a0a5966020212;hpb=6415d986ba32373d3c3915ec77473dfa2e2b7ad3;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 7024f974d5..8ca74103a2 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -562,13 +562,13 @@ Buffer::~Buffer() } -Buffer * Buffer::cloneFromMaster() const +Buffer * Buffer::cloneWithChildren() const { BufferMap bufmap; cloned_buffers.push_back(new CloneList); CloneList * clones = cloned_buffers.back(); - masterBuffer()->cloneWithChildren(bufmap, clones); + cloneWithChildren(bufmap, clones); // make sure we got cloned BufferMap::const_iterator bit = bufmap.find(this); @@ -888,6 +888,7 @@ int Buffer::readHeader(Lexer & lex) params().options.erase(); params().master.erase(); params().float_placement.erase(); + params().float_alignment.erase(); params().paperwidth.erase(); params().paperheight.erase(); params().leftmargin.erase(); @@ -1040,6 +1041,10 @@ bool Buffer::readDocument(Lexer & lex) << absFileName() << ") does not include " "this document. Ignoring the master assignment."); + // If the master has just been created, un-hide it (#11162) + if (!master->fileName().exists()) + lyx::dispatch(FuncRequest(LFUN_BUFFER_SWITCH, + master->absFileName())); } } } @@ -1102,7 +1107,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; @@ -1327,14 +1334,37 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, FileName Buffer::getBackupName() const { + map const file_formats = { + {544, "23"}, + {508, "22"}, + {474, "21"}, + {413, "20"}, + {345, "16"}, + {276, "15"}, + {245, "14"}, + {221, "13"}, + {220, "12"}, + {218, "1163"}, + {217, "116"}, + {216, "115"}, + {215, "11"}, + {210, "010"}, + {200, "006"} + }; FileName const & fn = fileName(); string const fname = fn.onlyFileNameWithoutExt(); string const fext = fn.extension() + "~"; string const fpath = lyxrc.backupdir_path.empty() ? fn.onlyPath().absFileName() : lyxrc.backupdir_path; - string const fform = convert(d->file_format); - string const backname = fname + "-lyxformat-" + fform; + string backup_suffix; + // If file format is from a stable series use version instead of file format + auto const it = file_formats.find(d->file_format); + if (it != file_formats.end()) + backup_suffix = "-lyx" + it->second; + else + backup_suffix = "-lyxformat-" + convert(d->file_format); + string const backname = fname + backup_suffix; FileName backup(addName(fpath, addExtension(backname, fext))); // limit recursion, just in case @@ -1658,7 +1688,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 +1712,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 +1729,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 +1756,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 +1778,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 +1786,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 @@ -1776,6 +1809,9 @@ void Buffer::writeLaTeXSource(otexstream & os, // (or not reached) and characters encodable in the current // encoding are not converted to ASCII-representation. + // Some macros rely on font encoding + runparams.main_fontenc = params().main_font_encoding(); + // If we are compiling a file standalone, even if this is the // child of some other buffer, let's cut the link here, so the // file is really independent and no concurring settings from @@ -1866,8 +1902,7 @@ void Buffer::writeLaTeXSource(otexstream & os, "file path name."), inputpath, uncodable_glyphs)); } else { - string docdir = - latex_path(original_path); + string docdir = os::latex_path(original_path); if (contains(docdir, '#')) { docdir = subst(docdir, "#", "\\#"); os << "\\catcode`\\#=11" @@ -1878,9 +1913,20 @@ void Buffer::writeLaTeXSource(otexstream & os, os << "\\catcode`\\%=11" "\\def\\%{%}\\catcode`\\%=14\n"; } + bool const detokenize = !isAscii(from_utf8(docdir)); + bool const quote = contains(docdir, ' '); os << "\\makeatletter\n" - << "\\def\\input@path{{" - << docdir << "}}\n" + << "\\def\\input@path{{"; + if (detokenize) + os << "\\detokenize{"; + if (quote) + os << "\""; + os << docdir; + if (quote) + os << "\""; + if (detokenize) + os << "}"; + os << "}}\n" << "\\makeatother\n"; } } @@ -1951,7 +1997,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 +2020,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 +2042,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 +2054,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 +2147,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 +2283,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 << "\n"; } if (output_preamble) os << "\n"; + + return ExportSuccess; } @@ -2251,7 +2317,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()); @@ -2349,7 +2420,8 @@ BiblioInfo const & Buffer::bibInfo() const } -void Buffer::registerBibfiles(FileNamePairList const & bf) const { +void Buffer::registerBibfiles(FileNamePairList const & bf) const +{ // We register the bib files in the master buffer, // if there is one, but also in every single buffer, // in case a child is compiled alone. @@ -2397,17 +2469,17 @@ void Buffer::checkIfBibInfoCacheIsValid() const } -void Buffer::reloadBibInfoCache() const +void Buffer::reloadBibInfoCache(bool const force) const { // use the master's cache Buffer const * const tmp = masterBuffer(); if (tmp != this) { - tmp->reloadBibInfoCache(); + tmp->reloadBibInfoCache(force); return; } checkIfBibInfoCacheIsValid(); - if (d->bibinfo_cache_valid_) + if (d->bibinfo_cache_valid_ && !force) return; d->bibinfo_.clear(); @@ -3150,9 +3222,28 @@ vector const Buffer::prepareBibFilePaths(OutputParams const & runpara string utf8input = to_utf8(bit.first); string database = prepareFileNameForLaTeX(utf8input, ".bib", runparams.nice); - FileName const try_in_file = + FileName try_in_file = makeAbsPath(database + ".bib", filePath()); - bool const not_from_texmf = try_in_file.isReadableFile(); + bool not_from_texmf = try_in_file.isReadableFile(); + // If the file has not been found, try with the real file name + // (it might come from a child in a sub-directory) + if (!not_from_texmf) { + try_in_file = bit.second; + if (try_in_file.isReadableFile()) { + // Check if the file is in texmf + FileName kpsefile(findtexfile(changeExtension(utf8input, "bib"), "bib", true)); + not_from_texmf = kpsefile.empty() + || kpsefile.absFileName() != try_in_file.absFileName(); + if (not_from_texmf) + // If this exists, make path relative to the master + // FIXME Unicode + database = + removeExtension(prepareFileNameForLaTeX( + to_utf8(makeRelPath(from_utf8(try_in_file.absFileName()), + from_utf8(filePath()))), + ".bib", runparams.nice)); + } + } if (!runparams.inComment && !runparams.dryrun && !runparams.nice && not_from_texmf) { @@ -3817,6 +3908,9 @@ unique_ptr Buffer::getSourceCode(odocstream & os, string const & format, // No side effect of file copying and image conversion runparams.dryrun = true; + // Some macros rely on font encoding + runparams.main_fontenc = params().main_font_encoding(); + if (output == CurrentParagraph) { runparams.par_begin = par_begin; runparams.par_end = par_end; @@ -4248,6 +4342,7 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir return ExportNoPathToFormat; } runparams.flavor = converters.getFlavor(path, this); + runparams.hyperref_driver = converters.getHyperrefDriver(path); for (auto const & edge : path) if (theConverters().get(edge).nice()) { need_nice_file = true; @@ -4277,40 +4372,53 @@ 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"), - _("The directory path to the document cannot contain spaces.")); + bformat(_("The directory path to the document\n%1$s\n" + "contains spaces, but your TeX installation does " + "not allow them. You should save the file to a directory " + "whose name does not contain spaces."), from_ascii(filePath()))); 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; } @@ -4319,9 +4427,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. @@ -4660,8 +4771,9 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const DocumentClass const & textclass = master->params().documentClass(); FileNamePairList old_bibfiles; - // do this only if we are the top-level Buffer - if (master == this) { + // Do this only if we are the top-level Buffer. We also need to account + // for the case of a previewed child with ignored parent here. + if (master == this && !d->ignore_parent) { textclass.counters().reset(from_ascii("bibitem")); reloadBibInfoCache(); // we will re-read this cache as we go through, but we need @@ -4722,9 +4834,13 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const return; // if the bibfiles changed, the cache of bibinfo is invalid - sort(d->bibfiles_cache_.begin(), d->bibfiles_cache_.end()); - // the old one should already be sorted - if (old_bibfiles != d->bibfiles_cache_) { + FileNamePairList new_bibfiles = d->bibfiles_cache_; + // this is a trick to determine whether the two vectors have + // the same elements. + sort(new_bibfiles.begin(), new_bibfiles.end()); + sort(old_bibfiles.begin(), old_bibfiles.end()); + if (old_bibfiles != new_bibfiles) { + LYXERR(Debug::FILES, "Reloading bibinfo cache."); invalidateBibinfoCache(); reloadBibInfoCache(); // We relied upon the bibinfo cache when recalculating labels. But that @@ -4734,10 +4850,21 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const // labels. Nothing else will have changed. So we could create a new // UpdateType that would signal that fact, if we needed to do so. parit = cbuf.par_iterator_begin(); + // we will be re-doing the counters and references and such. + textclass.counters().reset(); + clearReferenceCache(); + // we should not need to do this again? + // updateMacros(); + setChangesPresent(false); updateBuffer(parit, utype); + // this will already have been done by reloadBibInfoCache(); + // d->bibinfo_cache_valid_ = true; } - else + else { + LYXERR(Debug::FILES, "Bibfiles unchanged."); + // this is also set to true on the other path, by reloadBibInfoCache. d->bibinfo_cache_valid_ = true; + } d->cite_labels_valid_ = true; /// FIXME: Perf cbuf.tocBackend().update(true, utype);