X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fbuffer.C;h=2ce60e9dfc2310db0740ea1a79fd8fe1aa7b01e7;hb=368f6a53a87eb5997433ecd0f51e854c99360d28;hp=a03aface32c044eba9dc2424ae90f3976991759b;hpb=cf4293824f406c03e940bed6bf7274b57629a857;p=lyx.git diff --git a/src/buffer.C b/src/buffer.C index a03aface32..2ce60e9dfc 100644 --- a/src/buffer.C +++ b/src/buffer.C @@ -41,7 +41,6 @@ #include "output.h" #include "output_docbook.h" #include "output_latex.h" -#include "output_linuxdoc.h" #include "paragraph.h" #include "paragraph_funcs.h" #include "ParagraphParameters.h" @@ -56,20 +55,23 @@ #include "insets/insetinclude.h" #include "insets/insettext.h" -#include "mathed/math_macrotemplate.h" -#include "mathed/math_macrotable.h" -#include "mathed/math_support.h" +#include "mathed/MathMacroTemplate.h" +#include "mathed/MathMacroTable.h" +#include "mathed/MathSupport.h" #include "frontends/Alert.h" +#include "frontends/Application.h" #include "graphics/Previews.h" +#include "support/types.h" #include "support/lyxalgo.h" #include "support/filetools.h" #include "support/fs_extras.h" -#ifdef USE_COMPRESSION -# include "support/gzstream.h" -#endif +# include +# include +# include +namespace io = boost::iostreams; #include "support/lyxlib.h" #include "support/os.h" #include "support/path.h" @@ -77,6 +79,7 @@ #include "support/convert.h" #include +#include #include #if defined (HAVE_UTIME_H) @@ -91,6 +94,7 @@ #include +using lyx::docstring; using lyx::pos_type; using lyx::pit_type; @@ -110,7 +114,6 @@ using lyx::support::makeDisplayPath; using lyx::support::makeLatexName; using lyx::support::onlyFilename; using lyx::support::onlyPath; -using lyx::support::Path; using lyx::support::quoteName; using lyx::support::removeAutosaveFile; using lyx::support::rename; @@ -139,12 +142,9 @@ using std::vector; using std::string; -// all these externs should eventually be removed. -extern BufferList bufferlist; - namespace { -int const LYX_FORMAT = 245; +int const LYX_FORMAT = 249; } // namespace anon @@ -181,9 +181,6 @@ public: /// name of the file the buffer is associated with. string filename; - /// The path to the document file. - string filepath; - boost::scoped_ptr messages; /** Set to true only when the file is fully loaded. @@ -202,12 +199,13 @@ public: Buffer::Impl::Impl(Buffer & parent, string const & file, bool readonly_) : lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_), - filename(file), filepath(onlyPath(file)), file_fully_loaded(false), + filename(file), file_fully_loaded(false), inset(params) { inset.setAutoBreakRows(true); lyxvc.buffer(&parent); temppath = createBufferTmpDir(); + params.filepath = onlyPath(file); // FIXME: And now do something if temppath == string(), because we // assume from now on that temppath points to a valid temp dir. // See http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg67406.html @@ -231,7 +229,8 @@ Buffer::~Buffer() if (!temppath().empty() && !destroyDir(temppath())) { Alert::warning(_("Could not remove temporary directory"), - bformat(_("Could not remove the temporary directory %1$s"), temppath())); + bformat(_("Could not remove the temporary directory %1$s"), + lyx::from_utf8(temppath()))); } // Remove any previewed LaTeX snippets associated with this buffer. @@ -377,7 +376,7 @@ void Buffer::setReadonly(bool const flag) void Buffer::setFileName(string const & newfile) { pimpl_->filename = makeAbsPath(newfile); - pimpl_->filepath = onlyPath(pimpl_->filename); + params().filepath = onlyPath(pimpl_->filename); setReadonly(fs::is_readonly(pimpl_->filename)); updateTitles(); } @@ -389,8 +388,8 @@ namespace { void unknownClass(string const & unknown) { Alert::warning(_("Unknown document class"), - bformat(_("Using the default document class, because the " - "class %1$s is unknown."), unknown)); + bformat(_("Using the default document class, because the " + "class %1$s is unknown."), lyx::from_utf8(unknown))); } } // anon @@ -417,6 +416,8 @@ int Buffer::readHeader(LyXLex & lex) params().headsep.erase(); params().footskip.erase(); + ErrorList & errorList = errorLists_["Parse"]; + while (lex.isOK()) { lex.next(); string const token = lex.getString(); @@ -442,19 +443,21 @@ int Buffer::readHeader(LyXLex & lex) unknownClass(unknown); } else { ++unknown_tokens; - string const s = bformat(_("Unknown token: " - "%1$s %2$s\n"), - token, - lex.getString()); - error(ErrorItem(_("Document header error"), s, - -1, 0, 0)); + docstring const s = bformat(_("Unknown token: " + "%1$s %2$s\n"), + lyx::from_utf8(token), + lyx::from_utf8(lex.getString())); + errorList.push_back(ErrorItem(_("Document header error"), + s, -1, 0, 0)); } } } if (begin_header_line) { - string const s = _("\\begin_header is missing"); - error(ErrorItem(_("Document header error"), s, -1, 0, 0)); + docstring const s = _("\\begin_header is missing"); + errorList.push_back(ErrorItem(_("Document header error"), + s, -1, 0, 0)); } + return unknown_tokens; } @@ -464,29 +467,35 @@ int Buffer::readHeader(LyXLex & lex) // Returns false if "\end_document" is not read (Asger) bool Buffer::readDocument(LyXLex & lex) { + ErrorList & errorList = errorLists_["Parse"]; + errorList.clear(); + lex.next(); string const token = lex.getString(); if (token != "\\begin_document") { - string const s = _("\\begin_document is missing"); - error(ErrorItem(_("Document header error"), s, -1, 0, 0)); + docstring const s = _("\\begin_document is missing"); + errorList.push_back(ErrorItem(_("Document header error"), + s, -1, 0, 0)); } // we are reading in a brand new document BOOST_ASSERT(paragraphs().empty()); readHeader(lex); - if (!params().getLyXTextClass().load()) { + if (!params().getLyXTextClass().load(filePath())) { string theclass = params().getLyXTextClass().name(); Alert::error(_("Can't load document class"), bformat( - "Using the default document class, because the " - " class %1$s could not be loaded.", theclass)); + _("Using the default document class, because the " + " class %1$s could not be loaded."), lyx::from_utf8(theclass))); params().textclass = 0; } - bool const res = text().read(*this, lex); + bool const res = text().read(*this, lex, errorList); for_each(text().paragraphs().begin(), text().paragraphs().end(), bind(&Paragraph::setInsetOwner, _1, &inset())); + updateBibfilesCache(); + return res; } @@ -494,13 +503,13 @@ bool Buffer::readDocument(LyXLex & lex) // needed to insert the selection void Buffer::insertStringAsLines(ParagraphList & pars, pit_type & pit, pos_type & pos, - LyXFont const & fn, string const & str, bool autobreakrows) + LyXFont const & fn, docstring const & str, bool autobreakrows) { LyXFont font = fn; // insert the string, don't insert doublespace bool space_inserted = true; - for (string::const_iterator cit = str.begin(); + for (docstring::const_iterator cit = str.begin(); cit != str.end(); ++cit) { Paragraph & par = pars[pit]; if (*cit == '\n') { @@ -531,9 +540,11 @@ void Buffer::insertStringAsLines(ParagraphList & pars, } space_inserted = true; } +/* FIXME: not needed anymore? } else if (!isPrintable(*cit)) { // Ignore unprintables continue; +*/ } else { // just insert the character par.insertChar(pos, *cit, font); @@ -557,14 +568,15 @@ bool Buffer::readFile(string const & filename) paragraphs().clear(); LyXLex lex(0, 0); lex.setFile(filename); - bool ret = readFile(lex, filename); + if (!readFile(lex, filename)) + return false; // After we have read a file, we must ensure that the buffer // language is set and used in the gui. // If you know of a better place to put this, please tell me. (Lgb) updateDocLang(params().language); - return ret; + return true; } @@ -586,7 +598,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) if (!lex.isOK()) { Alert::error(_("Document could not be read"), - bformat(_("%1$s could not be read."), filename)); + bformat(_("%1$s could not be read."), lyx::from_utf8(filename))); return false; } @@ -595,7 +607,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) if (!lex.isOK()) { Alert::error(_("Document could not be read"), - bformat(_("%1$s could not be read."), filename)); + bformat(_("%1$s could not be read."), lyx::from_utf8(filename))); return false; } @@ -605,7 +617,7 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) Alert::error(_("Document format failure"), bformat(_("%1$s is not a LyX document."), - filename)); + lyx::from_utf8(filename))); return false; } @@ -627,8 +639,8 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) bformat(_("%1$s is from an earlier" " version of LyX, but a temporary" " file for converting it could" - " not be created."), - filename)); + " not be created."), + lyx::from_utf8(filename))); return false; } string const lyx2lyx = libFileSearch("lyx2lyx", "lyx2lyx"); @@ -637,12 +649,12 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) bformat(_("%1$s is from an earlier" " version of LyX, but the" " conversion script lyx2lyx" - " could not be found."), - filename)); + " could not be found."), + lyx::from_utf8(filename))); return false; } ostringstream command; - command << "python " << quoteName(lyx2lyx) + command << os::python() << ' ' << quoteName(lyx2lyx) << " -t " << convert(LYX_FORMAT) << " -o " << quoteName(tmpfile) << ' ' << quoteName(filename); @@ -657,8 +669,8 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) Alert::error(_("Conversion script failed"), bformat(_("%1$s is from an earlier version" " of LyX, but the lyx2lyx script" - " failed to convert it."), - filename)); + " failed to convert it."), + lyx::from_utf8(filename))); return false; } else { bool const ret = readFile(tmpfile); @@ -671,8 +683,8 @@ bool Buffer::readFile(LyXLex & lex, string const & filename) if (readDocument(lex)) { Alert::error(_("Document format failure"), bformat(_("%1$s ended unexpectedly, which means" - " that it is probably corrupted."), - filename)); + " that it is probably corrupted."), + lyx::from_utf8(filename))); } //lyxerr << "removing " << MacroTable::localMacros().size() @@ -702,14 +714,16 @@ bool Buffer::save() const // good enough. (Lgb) // But to use this we need fs::copy_file to actually do a copy, // even when the target file exists. (Lgb) - if (fs::exists(fileName()) && fs::is_writable(fs::path(fileName()).branch_path())) { - //try { + try { fs::copy_file(fileName(), s, false); - //} - //catch (fs::filesystem_error const & fe) { - //lyxerr << "LyX was not able to make backup copy. Beware.\n" - // << fe.what() << endl; - //} + } + catch (fs::filesystem_error const & fe) { + Alert::error(_("Backup failure"), + bformat(_("LyX was not able to make a backup copy in %1$s.\n" + "Please check if the directory exists and is writeable."), + lyx::from_utf8(fs::path(s).branch_path().native_directory_string()))); + lyxerr[Debug::DEBUG] << "Fs error: " + << fe.what() << endl; } } @@ -734,15 +748,11 @@ bool Buffer::writeFile(string const & fname) const bool retval = false; if (params().compressed) { -#ifdef USE_COMPRESSION - gz::ogzstream ofs(fname.c_str(), ios::out|ios::trunc); + io::filtering_ostream ofs(io::gzip_compressor() | io::file_sink(fname)); if (!ofs) return false; retval = do_writeFile(ofs); -#else - return false; -#endif } else { ofstream ofs(fname.c_str(), ios::out|ios::trunc); if (!ofs) @@ -815,7 +825,7 @@ void Buffer::makeLaTeXFile(string const & fname, if (!openFileWrite(ofs, fname)) return; - makeLaTeXFile(ofs, original_path, + writeLaTeXSource(ofs, original_path, runparams, output_preamble, output_body); ofs.close(); @@ -824,7 +834,7 @@ void Buffer::makeLaTeXFile(string const & fname, } -void Buffer::makeLaTeXFile(ostream & os, +void Buffer::writeLaTeXSource(ostream & os, string const & original_path, OutputParams const & runparams_in, bool const output_preamble, bool const output_body) @@ -951,12 +961,6 @@ bool Buffer::isLatex() const } -bool Buffer::isLinuxDoc() const -{ - return params().getLyXTextClass().outputType() == LINUXDOC; -} - - bool Buffer::isLiterate() const { return params().getLyXTextClass().outputType() == LITERATE; @@ -969,66 +973,17 @@ bool Buffer::isDocBook() const } -bool Buffer::isSGML() const -{ - LyXTextClass const & tclass = params().getLyXTextClass(); - - return tclass.outputType() == LINUXDOC || - tclass.outputType() == DOCBOOK; -} - - -void Buffer::makeLinuxDocFile(string const & fname, +void Buffer::makeDocBookFile(string const & fname, OutputParams const & runparams, bool const body_only) { + lyxerr[Debug::LATEX] << "makeDocBookFile..." << endl; + ofstream ofs; if (!openFileWrite(ofs, fname)) return; - LaTeXFeatures features(*this, params(), runparams); - validate(features); - - texrow().reset(); - - LyXTextClass const & tclass = params().getLyXTextClass(); - - string const & top_element = tclass.latexname(); - - if (!body_only) { - ofs << tclass.class_header(); - - string preamble = params().preamble; - string const name = runparams.nice ? changeExtension(pimpl_->filename, ".sgml") - : fname; - preamble += features.getIncludedFiles(name); - preamble += features.getLyXSGMLEntities(); - - if (!preamble.empty()) { - ofs << " [ " << preamble << " ]"; - } - ofs << ">\n\n"; - - if (params().options.empty()) - sgml::openTag(ofs, top_element); - else { - string top = top_element; - top += ' '; - top += params().options; - sgml::openTag(ofs, top); - } - } - - ofs << "\n"; - - linuxdocParagraphs(*this, paragraphs(), ofs, runparams); - - if (!body_only) { - ofs << "\n\n"; - sgml::closeTag(ofs, top_element); - } + writeDocBookSource(ofs, fname, runparams, body_only); ofs.close(); if (ofs.fail()) @@ -1036,14 +991,10 @@ void Buffer::makeLinuxDocFile(string const & fname, } -void Buffer::makeDocBookFile(string const & fname, +void Buffer::writeDocBookSource(ostream & os, string const & fname, OutputParams const & runparams, bool const only_body) { - ofstream ofs; - if (!openFileWrite(ofs, fname)) - return; - LaTeXFeatures features(*this, params(), runparams); validate(features); @@ -1054,17 +1005,17 @@ void Buffer::makeDocBookFile(string const & fname, if (!only_body) { if (runparams.flavor == OutputParams::XML) - ofs << "encoding()->name() << "\"?>\n"; - ofs << "\n\n"; + os << ">\n\n"; } string top = top_element; @@ -1098,20 +1049,16 @@ void Buffer::makeDocBookFile(string const & fname, top += params().options; } - ofs << "\n"; params().getLyXTextClass().counters().reset(); - sgml::openTag(ofs, top); - ofs << '\n'; - docbookParagraphs(paragraphs(), *this, ofs, runparams); - sgml::closeTag(ofs, top_element); - - ofs.close(); - if (ofs.fail()) - lyxerr << "File '" << fname << "' was not closed properly." << endl; + sgml::openTag(os, top); + os << '\n'; + docbookParagraphs(paragraphs(), *this, os, runparams); + sgml::closeTag(os, top_element); } @@ -1126,7 +1073,7 @@ int Buffer::runChktex() string const path = temppath(); string const org_path = filePath(); - Path p(path); // path to LaTeX file + lyx::support::Path p(path); // path to LaTeX file message(_("Running chktex...")); // Generate the LaTeX file if neccessary @@ -1143,12 +1090,14 @@ int Buffer::runChktex() Alert::error(_("chktex failure"), _("Could not run chktex successfully.")); } else if (res > 0) { - // Insert all errors as errors boxes - bufferErrors(*this, terr); + // Fill-in the error list with the TeX errors + bufferErrors(*this, terr, errorLists_["ChkTex"]); } busy(false); + errors("ChkTeX"); + return res; } @@ -1253,6 +1202,53 @@ void Buffer::fillWithBibKeys(vector > & keys) } +void Buffer::updateBibfilesCache() +{ + // if this is a child document and the parent is already loaded + // update the parent's cache instead + Buffer * tmp = getMasterBuffer(); + BOOST_ASSERT(tmp); + if (tmp != this) { + tmp->updateBibfilesCache(); + return; + } + + bibfilesCache_.clear(); + for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) { + if (it->lyxCode() == InsetBase::BIBTEX_CODE) { + InsetBibtex const & inset = + dynamic_cast(*it); + vector const bibfiles = inset.getFiles(*this); + bibfilesCache_.insert(bibfilesCache_.end(), + bibfiles.begin(), + bibfiles.end()); + } else if (it->lyxCode() == InsetBase::INCLUDE_CODE) { + InsetInclude & inset = + dynamic_cast(*it); + inset.updateBibfilesCache(*this); + vector const & bibfiles = + inset.getBibfilesCache(*this); + bibfilesCache_.insert(bibfilesCache_.end(), + bibfiles.begin(), + bibfiles.end()); + } + } +} + + +vector const & Buffer::getBibfilesCache() const +{ + // if this is a child document and the parent is already loaded + // use the parent's cache instead + Buffer const * tmp = getMasterBuffer(); + BOOST_ASSERT(tmp); + if (tmp != this) + return tmp->getBibfilesCache(); + + return bibfilesCache_; +} + + bool Buffer::isDepClean(string const & name) const { DepClean::const_iterator const it = pimpl_->dep_clean.find(name); @@ -1279,8 +1275,8 @@ bool Buffer::dispatch(FuncRequest const & func, bool * result) bool dispatched = true; switch (func.action) { - case LFUN_EXPORT: { - bool const tmp = Exporter::Export(this, func.argument, false); + case LFUN_BUFFER_EXPORT: { + bool const tmp = Exporter::Export(this, lyx::to_utf8(func.argument()), false); if (result) *result = tmp; break; @@ -1298,8 +1294,6 @@ void Buffer::changeLanguage(Language const * from, Language const * to) BOOST_ASSERT(from); BOOST_ASSERT(to); - lyxerr << "Changing Language!" << endl; - // Take care of l10n/i18n updateDocLang(to); @@ -1317,6 +1311,8 @@ void Buffer::updateDocLang(Language const * nlang) BOOST_ASSERT(nlang); pimpl_->messages.reset(new Messages(nlang->code())); + + updateLabels(*this); } @@ -1387,7 +1383,7 @@ Language const * Buffer::getLanguage() const } -string const Buffer::B_(string const & l10n) const +docstring const Buffer::B_(string const & l10n) const { if (pimpl_->messages.get()) { return pimpl_->messages->get(l10n); @@ -1467,7 +1463,7 @@ string const & Buffer::fileName() const string const & Buffer::filePath() const { - return pimpl_->filepath; + return params().filepath; } @@ -1486,8 +1482,21 @@ void Buffer::setParentName(string const & name) Buffer const * Buffer::getMasterBuffer() const { if (!params().parentname.empty() - && bufferlist.exists(params().parentname)) { - Buffer const * buf = bufferlist.getBuffer(params().parentname); + && theApp->bufferList().exists(params().parentname)) { + Buffer const * buf = theApp->bufferList().getBuffer(params().parentname); + if (buf) + return buf->getMasterBuffer(); + } + + return this; +} + + +Buffer * Buffer::getMasterBuffer() +{ + if (!params().parentname.empty() + && theApp->bufferList().exists(params().parentname)) { + Buffer * buf = theApp->bufferList().getBuffer(params().parentname); if (buf) return buf->getMasterBuffer(); } @@ -1575,3 +1584,52 @@ void Buffer::changeRefsIfUnique(string const & from, string const & to) } } } + + +void Buffer::getSourceCode(ostream & os, lyx::pit_type par_begin, lyx::pit_type par_end, bool full_source) +{ + OutputParams runparams; + runparams.nice = true; + runparams.flavor = OutputParams::LATEX; + runparams.linelen = lyxrc.ascii_linelen; + // No side effect of file copying and image conversion + runparams.dryrun = true; + + if (full_source) { + os << "% Preview source code\n\n"; + if (isLatex()) + writeLaTeXSource(os, filePath(), runparams, true, true); + else + writeDocBookSource(os, fileName(), runparams, false); + } else { + runparams.par_begin = par_begin; + runparams.par_end = par_end; + if (par_begin + 1 == par_end) + os << "% Preview source code for paragraph " << par_begin << "\n\n"; + else + os << "% Preview source code from paragraph " << par_begin << " to " << par_end - 1 << "\n\n"; + // output paragraphs + if (isLatex()) { + texrow().reset(); + latexParagraphs(*this, paragraphs(), os, texrow(), runparams); + } else // DocBook + docbookParagraphs(paragraphs(), *this, os, runparams); + } +} + + +ErrorList const & Buffer::errorList(string const & type) const +{ + static ErrorList const emptyErrorList; + std::map::const_iterator I = errorLists_.find(type); + if (I == errorLists_.end()) + return emptyErrorList; + + return I->second; +} + + +ErrorList & Buffer::errorList(string const & type) +{ + return errorLists_[type]; +}