X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=8955a448dc722d3bb2ef0ddd9876bb58228ae2b6;hb=4291d4b0ff6d0a6eb9b92b855e0c44d94ac6ccca;hp=50360c1e93fc9880cf3c08dcc87455a08c681fb1;hpb=b99433e73b1cb96553cd8558c7c2a5da72bb1f4f;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 50360c1e93..8955a448dc 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -4,6 +4,7 @@ * Licence details can be found in the file COPYING. * * \author Lars Gullik Bjønnes + * \author Stefan Schimanski * * Full author contact details are available in file CREDITS. */ @@ -22,7 +23,6 @@ #include "Chktex.h" #include "Converter.h" #include "Counters.h" -#include "debug.h" #include "DocIterator.h" #include "EmbeddedFiles.h" #include "Encoding.h" @@ -30,7 +30,6 @@ #include "Exporter.h" #include "Format.h" #include "FuncRequest.h" -#include "gettext.h" #include "InsetIterator.h" #include "InsetList.h" #include "Language.h" @@ -42,7 +41,6 @@ #include "LyX.h" #include "LyXRC.h" #include "LyXVC.h" -#include "Messages.h" #include "output_docbook.h" #include "output.h" #include "output_latex.h" @@ -68,8 +66,8 @@ #include "insets/InsetInclude.h" #include "insets/InsetText.h" -#include "mathed/MathMacroTemplate.h" #include "mathed/MacroTable.h" +#include "mathed/MathMacroTemplate.h" #include "mathed/MathSupport.h" #include "frontends/alert.h" @@ -79,26 +77,26 @@ #include "graphics/Previews.h" -#include "support/types.h" -#include "support/lyxalgo.h" +#include "support/convert.h" +#include "support/debug.h" #include "support/FileFilterList.h" #include "support/filetools.h" -#include "support/Forkedcall.h" -#include "support/fs_extras.h" +#include "support/ForkedCalls.h" +#include "support/gettext.h" #include "support/gzstream.h" +#include "support/lstrings.h" +#include "support/lyxalgo.h" #include "support/lyxlib.h" #include "support/os.h" #include "support/Path.h" #include "support/textutils.h" -#include "support/convert.h" +#include "support/types.h" #if !defined (HAVE_FORK) # define fork() -1 #endif #include -#include -#include #include #include @@ -147,16 +145,14 @@ using support::split; using support::subst; using support::tempName; using support::trim; -using support::sum; using support::suffixIs; namespace Alert = frontend::Alert; namespace os = support::os; -namespace fs = boost::filesystem; namespace { -int const LYX_FORMAT = 296; //RGH: InsetInclude changes +int const LYX_FORMAT = 303; // Uwe: Serbocroatian } // namespace anon @@ -171,7 +167,8 @@ public: BufferParams params; LyXVC lyxvc; string temppath; - TexRow texrow; + mutable TexRow texrow; + Buffer const * parent_buffer; /// need to regenerate .tex? DepClean dep_clean; @@ -201,10 +198,12 @@ public: InsetText inset; /// - MacroTable macros; + mutable TocBackend toc_backend; - /// - TocBackend toc_backend; + /// macro table + typedef std::map > PositionToMacroMap; + typedef std::map NameToPositionMacroMap; + NameToPositionMacroMap macros; /// Container for all sort of Buffer dependant errors. map errorLists; @@ -226,15 +225,15 @@ public: Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_) - : lyx_clean(true), bak_clean(true), unnamed(false), read_only(readonly_), - filename(file), file_fully_loaded(false), inset(params), - toc_backend(&parent), embedded_files(&parent), timestamp_(0), - checksum_(0), wa_(0), undo_(parent) + : parent_buffer(0), lyx_clean(true), bak_clean(true), unnamed(false), + read_only(readonly_), filename(file), file_fully_loaded(false), + inset(params), toc_backend(&parent), embedded_files(&parent), + timestamp_(0), checksum_(0), wa_(0), undo_(parent) { inset.setAutoBreakRows(true); lyxvc.setBuffer(&parent); temppath = createBufferTmpDir(); - params.filepath = onlyPath(file.absFilename()); + // 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 @@ -245,25 +244,27 @@ Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_) Buffer::Buffer(string const & file, bool readonly) - : pimpl_(new Impl(*this, FileName(file), readonly)), gui_(0) + : d(new Impl(*this, FileName(file), readonly)), gui_(0) { - LYXERR(Debug::INFO) << "Buffer::Buffer()" << endl; + LYXERR(Debug::INFO, "Buffer::Buffer()"); } Buffer::~Buffer() { - LYXERR(Debug::INFO) << "Buffer::~Buffer()" << endl; + LYXERR(Debug::INFO, "Buffer::~Buffer()"); // here the buffer should take care that it is // saved properly, before it goes into the void. - Buffer * master = masterBuffer(); + Buffer const * master = masterBuffer(); if (master != this && use_gui) // We are closing buf which was a child document so we // must update the labels and section numbering of its master // Buffer. updateLabels(*master); + resetChildDocuments(false); + if (!temppath().empty() && !FileName(temppath()).destroyDirectory()) { Alert::warning(_("Could not remove temporary directory"), bformat(_("Could not remove the temporary directory %1$s"), @@ -273,49 +274,49 @@ Buffer::~Buffer() // Remove any previewed LaTeX snippets associated with this buffer. graphics::Previews::get().removeLoader(*this); - if (pimpl_->wa_) { - pimpl_->wa_->closeAll(); - delete pimpl_->wa_; + if (d->wa_) { + d->wa_->closeAll(); + delete d->wa_; } - delete pimpl_; + delete d; } void Buffer::changed() const { - if (pimpl_->wa_) - pimpl_->wa_->redrawAll(); + if (d->wa_) + d->wa_->redrawAll(); } frontend::WorkAreaManager & Buffer::workAreaManager() const { - BOOST_ASSERT(pimpl_->wa_); - return *pimpl_->wa_; + BOOST_ASSERT(d->wa_); + return *d->wa_; } Text & Buffer::text() const { - return const_cast(pimpl_->inset.text_); + return const_cast(d->inset.text_); } Inset & Buffer::inset() const { - return const_cast(pimpl_->inset); + return const_cast(d->inset); } BufferParams & Buffer::params() { - return pimpl_->params; + return d->params; } BufferParams const & Buffer::params() const { - return pimpl_->params; + return d->params; } @@ -333,77 +334,69 @@ ParagraphList const & Buffer::paragraphs() const LyXVC & Buffer::lyxvc() { - return pimpl_->lyxvc; + return d->lyxvc; } LyXVC const & Buffer::lyxvc() const { - return pimpl_->lyxvc; + return d->lyxvc; } string const & Buffer::temppath() const { - return pimpl_->temppath; -} - - -TexRow & Buffer::texrow() -{ - return pimpl_->texrow; + return d->temppath; } TexRow const & Buffer::texrow() const { - return pimpl_->texrow; -} - - -TocBackend & Buffer::tocBackend() -{ - return pimpl_->toc_backend; + return d->texrow; } -TocBackend const & Buffer::tocBackend() const +TocBackend & Buffer::tocBackend() const { - return pimpl_->toc_backend; + return d->toc_backend; } EmbeddedFiles & Buffer::embeddedFiles() { - return pimpl_->embedded_files; + return d->embedded_files; } EmbeddedFiles const & Buffer::embeddedFiles() const { - return pimpl_->embedded_files; + return d->embedded_files; } Undo & Buffer::undo() { - return pimpl_->undo_; + return d->undo_; } string Buffer::latexName(bool const no_path) const { - string const name = changeExtension(makeLatexName(absFileName()), ".tex"); - return no_path ? onlyFilename(name) : name; + FileName latex_name = makeLatexName(d->filename); + return no_path ? latex_name.onlyFileName() + : latex_name.absFilename(); } -pair Buffer::logName() const +string Buffer::logName(LogType * type) const { string const filename = latexName(false); - if (filename.empty()) - return make_pair(Buffer::latexlog, string()); + if (filename.empty()) { + if (type) + *type = latexlog; + return string(); + } string const path = temppath(); @@ -419,18 +412,22 @@ pair Buffer::logName() const if (bname.exists() && (!fname.exists() || fname.lastModified() < bname.lastModified())) { - LYXERR(Debug::FILES) << "Log name calculated as: " << bname << endl; - return make_pair(Buffer::buildlog, bname.absFilename()); + LYXERR(Debug::FILES, "Log name calculated as: " << bname); + if (type) + *type = buildlog; + return bname.absFilename(); } - LYXERR(Debug::FILES) << "Log name calculated as: " << fname << endl; - return make_pair(Buffer::latexlog, fname.absFilename()); + LYXERR(Debug::FILES, "Log name calculated as: " << fname); + if (type) + *type = latexlog; + return fname.absFilename(); } void Buffer::setReadonly(bool const flag) { - if (pimpl_->read_only != flag) { - pimpl_->read_only = flag; + if (d->read_only != flag) { + d->read_only = flag; setReadOnly(flag); } } @@ -438,9 +435,8 @@ void Buffer::setReadonly(bool const flag) void Buffer::setFileName(string const & newfile) { - pimpl_->filename = makeAbsPath(newfile); - params().filepath = onlyPath(pimpl_->filename.absFilename()); - setReadonly(pimpl_->filename.isReadOnly()); + d->filename = makeAbsPath(newfile); + setReadonly(d->filename.isReadOnly()); updateTitles(); } @@ -474,7 +470,7 @@ int Buffer::readHeader(Lexer & lex) params().temp_bullet(i) = ITEMIZE_DEFAULTS[i]; } - ErrorList & errorList = pimpl_->errorLists["Parse"]; + ErrorList & errorList = d->errorLists["Parse"]; while (lex.isOK()) { lex.next(); @@ -492,10 +488,10 @@ int Buffer::readHeader(Lexer & lex) continue; } - LYXERR(Debug::PARSER) << "Handling document header token: `" - << token << '\'' << endl; + LYXERR(Debug::PARSER, "Handling document header token: `" + << token << '\''); - string unknown = params().readToken(lex, token); + string unknown = params().readToken(lex, token, d->filename.onlyPath()); if (!unknown.empty()) { if (unknown[0] != '\\' && token == "\\textclass") { Alert::warning(_("Unknown document class"), @@ -527,7 +523,7 @@ int Buffer::readHeader(Lexer & lex) // Returns false if "\end_document" is not read (Asger) bool Buffer::readDocument(Lexer & lex) { - ErrorList & errorList = pimpl_->errorLists["Parse"]; + ErrorList & errorList = d->errorLists["Parse"]; errorList.clear(); lex.next(); @@ -670,7 +666,7 @@ bool Buffer::readFile(FileName const & filename) string format = filename.guessFormatFromContents(); if (format == "zip") { // decompress to a temp directory - LYXERR(Debug::FILES) << filename << " is in zip format. Unzip to " << temppath() << endl; + LYXERR(Debug::FILES, filename << " is in zip format. Unzip to " << temppath()); ::unzipToDir(filename.toFilesystemEncoding(), temppath()); // FileName lyxfile(addName(temppath(), "content.lyx")); @@ -698,13 +694,13 @@ bool Buffer::readFile(FileName const & filename) bool Buffer::isFullyLoaded() const { - return pimpl_->file_fully_loaded; + return d->file_fully_loaded; } void Buffer::setFullyLoaded(bool value) { - pimpl_->file_fully_loaded = value; + d->file_fully_loaded = value; } @@ -752,11 +748,11 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, // save timestamp and checksum of the original disk file, making sure // to not overwrite them with those of the file created in the tempdir // when it has to be converted to the current format. - if (!pimpl_->checksum_) { + if (!d->checksum_) { // Save the timestamp and checksum of disk file. If filename is an - // emergency file, save the timestamp and sum of the original lyx file + // emergency file, save the timestamp and checksum of the original lyx file // because isExternallyModified will check for this file. (BUG4193) - string diskfile = filename.toFilesystemEncoding(); + string diskfile = filename.absFilename(); if (suffixIs(diskfile, ".emergency")) diskfile = diskfile.substr(0, diskfile.size() - 10); saveCheckSum(FileName(diskfile)); @@ -796,9 +792,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, << ' ' << quoteName(filename.toFilesystemEncoding()); string const command_str = command.str(); - LYXERR(Debug::INFO) << "Running '" - << command_str << '\'' - << endl; + LYXERR(Debug::INFO, "Running '" << command_str << '\''); cmd_ret const ret = runCommand(command_str); if (ret.first != 0) { @@ -823,11 +817,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, from_utf8(filename.absFilename()))); } - //lyxerr << "removing " << MacroTable::localMacros().size() - // << " temporary macro entries" << endl; - //MacroTable::localMacros().clear(); - - pimpl_->file_fully_loaded = true; + d->file_fully_loaded = true; return success; } @@ -838,35 +828,33 @@ bool Buffer::save() const // We don't need autosaves in the immediate future. (Asger) resetAutosaveTimers(); - string const encodedFilename = pimpl_->filename.toFilesystemEncoding(); + string const encodedFilename = d->filename.toFilesystemEncoding(); FileName backupName; bool madeBackup = false; // make a backup if the file already exists - if (lyxrc.make_backup && fs::exists(encodedFilename)) { + if (lyxrc.make_backup && fileName().exists()) { backupName = FileName(absFileName() + '~'); if (!lyxrc.backupdir_path.empty()) { string const mangledName = - subst(subst(os::internal_path( - backupName.absFilename()), '/', '!'), ':', '!'); + subst(subst(backupName.absFilename(), '/', '!'), ':', '!'); backupName = FileName(addName(lyxrc.backupdir_path, mangledName)); } - try { - fs::copy_file(encodedFilename, backupName.toFilesystemEncoding(), false); + if (fileName().copyTo(backupName, true)) { madeBackup = true; - } catch (fs::filesystem_error const & fe) { + } else { Alert::error(_("Backup failure"), bformat(_("Cannot create backup file %1$s.\n" "Please check whether the directory exists and is writeable."), from_utf8(backupName.absFilename()))); - LYXERR(Debug::DEBUG) << "Fs error: " << fe.what() << endl; + //LYXERR(Debug::DEBUG, "Fs error: " << fe.what()); } } // ask if the disk file has been externally modified (use checksum method) - if (fs::exists(encodedFilename) && isExternallyModified(checksum_method)) { + if (fileName().exists() && isExternallyModified(checksum_method)) { docstring const file = makeDisplayPath(absFileName(), 20); docstring text = bformat(_("Document %1$s has been externally modified. Are you sure " "you want to overwrite this file?"), file); @@ -876,15 +864,15 @@ bool Buffer::save() const return false; } - if (writeFile(pimpl_->filename)) { + if (writeFile(d->filename)) { markClean(); removeAutosaveFile(absFileName()); - saveCheckSum(pimpl_->filename); + saveCheckSum(d->filename); return true; } else { // Saving failed, so backup is not backup if (madeBackup) - rename(backupName, pimpl_->filename); + rename(backupName, d->filename); return false; } } @@ -892,7 +880,7 @@ bool Buffer::save() const bool Buffer::writeFile(FileName const & fname) const { - if (pimpl_->read_only && fname == pimpl_->filename) + if (d->read_only && fname == d->filename) return false; bool retval = false; @@ -921,7 +909,7 @@ bool Buffer::writeFile(FileName const & fname) const if (retval && params().embedded) { // write file.lyx and all the embedded files to the zip file fname // if embedding is enabled - return pimpl_->embedded_files.writeFile(fname); + return d->embedded_files.writeFile(fname); } return retval; } @@ -948,7 +936,7 @@ bool Buffer::write(ostream & ofs) const AuthorList::Authors::const_iterator a_it = params().authors().begin(); AuthorList::Authors::const_iterator a_end = params().authors().end(); for (; a_it != a_end; ++a_it) - a_it->second.used(false); + a_it->second.setUsed(false); ParIterator const end = par_iterator_end(); ParIterator it = par_iterator_begin(); @@ -992,11 +980,10 @@ bool Buffer::write(ostream & ofs) const bool Buffer::makeLaTeXFile(FileName const & fname, string const & original_path, OutputParams const & runparams, - bool output_preamble, bool output_body) + bool output_preamble, bool output_body) const { string const encoding = runparams.encoding->iconvName(); - LYXERR(Debug::LATEX) << "makeLaTeXFile encoding: " - << encoding << "..." << endl; + LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << "..."); odocfstream ofs(encoding); if (!openFileWrite(ofs, fname)) @@ -1006,7 +993,7 @@ bool Buffer::makeLaTeXFile(FileName const & fname, bool failed_export = false; try { - texrow().reset(); + d->texrow.reset(); writeLaTeXSource(ofs, original_path, runparams, output_preamble, output_body); } @@ -1044,15 +1031,15 @@ bool Buffer::makeLaTeXFile(FileName const & fname, void Buffer::writeLaTeXSource(odocstream & os, string const & original_path, OutputParams const & runparams_in, - bool const output_preamble, bool const output_body) + bool const output_preamble, bool const output_body) const { OutputParams runparams = runparams_in; // validate the buffer. - LYXERR(Debug::LATEX) << " Validating buffer..." << endl; + LYXERR(Debug::LATEX, " Validating buffer..."); LaTeXFeatures features(*this, params(), runparams); validate(features); - LYXERR(Debug::LATEX) << " Buffer validation done." << endl; + LYXERR(Debug::LATEX, " Buffer validation done."); // The starting paragraph of the coming rows is the // first paragraph of the document. (Asger) @@ -1061,10 +1048,10 @@ void Buffer::writeLaTeXSource(odocstream & os, "For more info, see http://www.lyx.org/.\n" "%% Do not edit unless you really know what " "you are doing.\n"; - texrow().newline(); - texrow().newline(); + d->texrow.newline(); + d->texrow.newline(); } - LYXERR(Debug::INFO) << "lyx document header finished" << endl; + LYXERR(Debug::INFO, "lyx document header finished"); // There are a few differences between nice LaTeX and usual files: // usual is \batchmode and has a // special input@path to allow the including of figures @@ -1080,7 +1067,7 @@ void Buffer::writeLaTeXSource(odocstream & os, // code for usual, NOT nice-latex-file os << "\\batchmode\n"; // changed // from \nonstopmode - texrow().newline(); + d->texrow.newline(); } if (!original_path.empty()) { // FIXME UNICODE @@ -1090,25 +1077,25 @@ void Buffer::writeLaTeXSource(odocstream & os, << "\\def\\input@path{{" << inputpath << "/}}\n" << "\\makeatother\n"; - texrow().newline(); - texrow().newline(); - texrow().newline(); + d->texrow.newline(); + d->texrow.newline(); + d->texrow.newline(); } // Write the preamble - runparams.use_babel = params().writeLaTeX(os, features, texrow()); + runparams.use_babel = params().writeLaTeX(os, features, d->texrow); if (!output_body) return; // make the body. os << "\\begin{document}\n"; - texrow().newline(); + d->texrow.newline(); } // output_preamble - texrow().start(paragraphs().begin()->id(), 0); + d->texrow.start(paragraphs().begin()->id(), 0); - LYXERR(Debug::INFO) << "preamble finished, now the body." << endl; + LYXERR(Debug::INFO, "preamble finished, now the body."); if (!lyxrc.language_auto_begin && !params().language->babel().empty()) { @@ -1117,7 +1104,7 @@ void Buffer::writeLaTeXSource(odocstream & os, "$$lang", params().language->babel())) << '\n'; - texrow().newline(); + d->texrow.newline(); } Encoding const & encoding = params().encoding(); @@ -1127,37 +1114,37 @@ void Buffer::writeLaTeXSource(odocstream & os, // the preamble if it is handled by CJK.sty. os << "\\begin{CJK}{" << from_ascii(encoding.latexName()) << "}{}\n"; - texrow().newline(); + d->texrow.newline(); } // if we are doing a real file with body, even if this is the // child of some other buffer, let's cut the link here. // This happens for example if only a child document is printed. - string save_parentname; + Buffer const * save_parent = 0; if (output_preamble) { - save_parentname = params().parentname; - params().parentname.erase(); + save_parent = d->parent_buffer; + d->parent_buffer = 0; } loadChildDocuments(); // the real stuff - latexParagraphs(*this, paragraphs(), os, texrow(), runparams); + latexParagraphs(*this, paragraphs(), os, d->texrow, runparams); // Restore the parenthood if needed if (output_preamble) - params().parentname = save_parentname; + d->parent_buffer = save_parent; // add this just in case after all the paragraphs os << endl; - texrow().newline(); + d->texrow.newline(); if (encoding.package() == Encoding::CJK) { // Close the open CJK environment. // latexParagraphs will have opened one even if the last text // was not CJK. os << "\\end{CJK}\n"; - texrow().newline(); + d->texrow.newline(); } if (!lyxrc.language_auto_end && @@ -1166,26 +1153,23 @@ void Buffer::writeLaTeXSource(odocstream & os, "$$lang", params().language->babel())) << '\n'; - texrow().newline(); + d->texrow.newline(); } if (output_preamble) { os << "\\end{document}\n"; - texrow().newline(); - - LYXERR(Debug::LATEX) << "makeLaTeXFile...done" << endl; + d->texrow.newline(); + LYXERR(Debug::LATEX, "makeLaTeXFile...done"); } else { - LYXERR(Debug::LATEX) << "LaTeXFile for inclusion made." - << endl; + LYXERR(Debug::LATEX, "LaTeXFile for inclusion made."); } runparams_in.encoding = runparams.encoding; // Just to be sure. (Asger) - texrow().newline(); + d->texrow.newline(); - LYXERR(Debug::INFO) << "Finished making LaTeX file." << endl; - LYXERR(Debug::INFO) << "Row count was " << texrow().rows() - 1 - << '.' << endl; + LYXERR(Debug::INFO, "Finished making LaTeX file."); + LYXERR(Debug::INFO, "Row count was " << d->texrow.rows() - 1 << '.'); } @@ -1209,9 +1193,9 @@ bool Buffer::isDocBook() const void Buffer::makeDocBookFile(FileName const & fname, OutputParams const & runparams, - bool const body_only) + bool const body_only) const { - LYXERR(Debug::LATEX) << "makeDocBookFile..." << endl; + LYXERR(Debug::LATEX, "makeDocBookFile..."); //ofstream ofs; odocfstream ofs; @@ -1228,12 +1212,12 @@ void Buffer::makeDocBookFile(FileName const & fname, void Buffer::writeDocBookSource(odocstream & os, string const & fname, OutputParams const & runparams, - bool const only_body) + bool const only_body) const { LaTeXFeatures features(*this, params(), runparams); validate(features); - texrow().reset(); + d->texrow.reset(); TextClass const & tclass = params().getTextClass(); string const top_element = tclass.latexname(); @@ -1312,7 +1296,7 @@ int Buffer::runChktex() string const name = addName(path.absFilename(), latexName()); string const org_path = filePath(); - support::Path p(path); // path to LaTeX file + support::PathChanger p(path); // path to LaTeX file message(_("Running chktex...")); // Generate the LaTeX file if neccessary @@ -1329,7 +1313,7 @@ int Buffer::runChktex() Alert::error(_("chktex failure"), _("Could not run chktex successfully.")); } else if (res > 0) { - ErrorList & errlist = pimpl_->errorLists["ChkTeX"]; + ErrorList & errlist = d->errorLists["ChkTeX"]; errlist.clear(); bufferErrors(terr, errlist); } @@ -1437,11 +1421,11 @@ void Buffer::getLabelList(vector & list) const } -void Buffer::updateBibfilesCache() +void Buffer::updateBibfilesCache() const { // if this is a child document and the parent is already loaded // update the parent's cache instead - Buffer * tmp = masterBuffer(); + Buffer const * tmp = masterBuffer(); BOOST_ASSERT(tmp); if (tmp != this) { tmp->updateBibfilesCache(); @@ -1490,8 +1474,8 @@ vector const & Buffer::getBibfilesCache() const bool Buffer::isDepClean(string const & name) const { - DepClean::const_iterator const it = pimpl_->dep_clean.find(name); - if (it == pimpl_->dep_clean.end()) + DepClean::const_iterator const it = d->dep_clean.find(name); + if (it == d->dep_clean.end()) return true; return it->second; } @@ -1499,7 +1483,7 @@ bool Buffer::isDepClean(string const & name) const void Buffer::markDepClean(string const & name) { - pimpl_->dep_clean[name] = true; + d->dep_clean[name] = true; } @@ -1614,184 +1598,230 @@ docstring const Buffer::B_(string const & l10n) const bool Buffer::isClean() const { - return pimpl_->lyx_clean; + return d->lyx_clean; } bool Buffer::isBakClean() const { - return pimpl_->bak_clean; + return d->bak_clean; } bool Buffer::isExternallyModified(CheckMethod method) const { - BOOST_ASSERT(pimpl_->filename.exists()); + BOOST_ASSERT(d->filename.exists()); // if method == timestamp, check timestamp before checksum return (method == checksum_method - || pimpl_->timestamp_ != pimpl_->filename.lastModified()) - && pimpl_->checksum_ != sum(pimpl_->filename); + || d->timestamp_ != d->filename.lastModified()) + && d->checksum_ != d->filename.checksum(); } void Buffer::saveCheckSum(FileName const & file) const { if (file.exists()) { - pimpl_->timestamp_ = file.lastModified(); - pimpl_->checksum_ = sum(file); + d->timestamp_ = file.lastModified(); + d->checksum_ = file.checksum(); } else { // in the case of save to a new file. - pimpl_->timestamp_ = 0; - pimpl_->checksum_ = 0; + d->timestamp_ = 0; + d->checksum_ = 0; } } void Buffer::markClean() const { - if (!pimpl_->lyx_clean) { - pimpl_->lyx_clean = true; + if (!d->lyx_clean) { + d->lyx_clean = true; updateTitles(); } // if the .lyx file has been saved, we don't need an // autosave - pimpl_->bak_clean = true; + d->bak_clean = true; } void Buffer::markBakClean() const { - pimpl_->bak_clean = true; + d->bak_clean = true; } void Buffer::setUnnamed(bool flag) { - pimpl_->unnamed = flag; + d->unnamed = flag; } bool Buffer::isUnnamed() const { - return pimpl_->unnamed; + return d->unnamed; } // FIXME: this function should be moved to buffer_pimpl.C void Buffer::markDirty() { - if (pimpl_->lyx_clean) { - pimpl_->lyx_clean = false; + if (d->lyx_clean) { + d->lyx_clean = false; updateTitles(); } - pimpl_->bak_clean = false; + d->bak_clean = false; - DepClean::iterator it = pimpl_->dep_clean.begin(); - DepClean::const_iterator const end = pimpl_->dep_clean.end(); + DepClean::iterator it = d->dep_clean.begin(); + DepClean::const_iterator const end = d->dep_clean.end(); for (; it != end; ++it) it->second = false; } +FileName Buffer::fileName() const +{ + return d->filename; +} + + string Buffer::absFileName() const { - return pimpl_->filename.absFilename(); + return d->filename.absFilename(); } -string const & Buffer::filePath() const +string Buffer::filePath() const { - return params().filepath; + return d->filename.onlyPath().absFilename(); } bool Buffer::isReadonly() const { - return pimpl_->read_only; + return d->read_only; } -void Buffer::setParentName(string const & name) +void Buffer::setParent(Buffer const * buffer) { - if (name == pimpl_->filename.absFilename()) - // Avoids recursive include. - params().parentname.clear(); - else - params().parentname = name; + // Avoids recursive include. + d->parent_buffer = buffer == this ? 0 : buffer; } -Buffer const * Buffer::masterBuffer() const +Buffer const * Buffer::parent() { - if (!params().parentname.empty() - && theBufferList().exists(params().parentname)) { - Buffer const * buf = theBufferList().getBuffer(params().parentname); - //We need to check if the parent is us... - //FIXME RECURSIVE INCLUDE - //This is not sufficient, since recursive includes could be downstream. - if (buf && buf != this) - return buf->masterBuffer(); - } + return d->parent_buffer; +} - return this; + +Buffer const * Buffer::masterBuffer() const +{ + if (!d->parent_buffer) + return this; + + return d->parent_buffer->masterBuffer(); } -Buffer * Buffer::masterBuffer() +bool Buffer::hasMacro(docstring const & name, Paragraph const & par) const { - if (!params().parentname.empty() - && theBufferList().exists(params().parentname)) { - Buffer * buf = theBufferList().getBuffer(params().parentname); - //We need to check if the parent is us... - //FIXME RECURSIVE INCLUDE - //This is not sufficient, since recursive includes could be downstream. - if (buf && buf != this) - return buf->masterBuffer(); - } + Impl::PositionToMacroMap::iterator it; + it = d->macros[name].upper_bound(par.macrocontextPosition()); + if (it != d->macros[name].end()) + return true; + + // If there is a master buffer, query that + Buffer const * master = masterBuffer(); + if (master && master != this) + return master->hasMacro(name); - return this; + return MacroTable::globalMacros().has(name); } -MacroData const & Buffer::getMacro(docstring const & name) const +bool Buffer::hasMacro(docstring const & name) const { - return pimpl_->macros.get(name); + if( !d->macros[name].empty() ) + return true; + + // If there is a master buffer, query that + Buffer const * master = masterBuffer(); + if (master && master != this) + return master->hasMacro(name); + + return MacroTable::globalMacros().has(name); } -bool Buffer::hasMacro(docstring const & name) const +MacroData const & Buffer::getMacro(docstring const & name, + Paragraph const & par) const { - return pimpl_->macros.has(name); + Impl::PositionToMacroMap::iterator it; + it = d->macros[name].upper_bound(par.macrocontextPosition()); + if( it != d->macros[name].end() ) + return it->second; + + // If there is a master buffer, query that + Buffer const * master = masterBuffer(); + if (master && master != this) + return master->getMacro(name); + + return MacroTable::globalMacros().get(name); } -void Buffer::insertMacro(docstring const & name, MacroData const & data) +MacroData const & Buffer::getMacro(docstring const & name) const { - MacroTable::globalMacros().insert(name, data); - pimpl_->macros.insert(name, data); + Impl::PositionToMacroMap::iterator it; + it = d->macros[name].begin(); + if( it != d->macros[name].end() ) + return it->second; + + // If there is a master buffer, query that + Buffer const * master = masterBuffer(); + if (master && master != this) + return master->getMacro(name); + + return MacroTable::globalMacros().get(name); } -void Buffer::buildMacros() +void Buffer::updateMacros() { - // Start with global table. - pimpl_->macros = MacroTable::globalMacros(); + // start with empty table + d->macros = Impl::NameToPositionMacroMap(); - // Now add our own. - ParagraphList const & pars = text().paragraphs(); + // Iterate over buffer + ParagraphList & pars = text().paragraphs(); for (size_t i = 0, n = pars.size(); i != n; ++i) { + // set position again + pars[i].setMacrocontextPosition(i); + //lyxerr << "searching main par " << i // << " for macro definitions" << std::endl; InsetList const & insets = pars[i].insetList(); InsetList::const_iterator it = insets.begin(); InsetList::const_iterator end = insets.end(); for ( ; it != end; ++it) { - //lyxerr << "found inset code " << it->inset->lyxCode() << std::endl; - if (it->inset->lyxCode() == MATHMACRO_CODE) { - MathMacroTemplate const & mac - = static_cast(*it->inset); - insertMacro(mac.name(), mac.asMacroData()); + if (it->inset->lyxCode() != MATHMACRO_CODE) + continue; + + // get macro data + MathMacroTemplate const & macroTemplate + = static_cast(*it->inset); + + // valid? + if (macroTemplate.validMacro()) { + MacroData macro = macroTemplate.asMacroData(); + + // redefinition? + // call hasMacro here instead of directly querying mc to + // also take the master document into consideration + macro.setRedefinition(hasMacro(macroTemplate.name())); + + // register macro (possibly overwrite the previous one of this paragraph) + d->macros[macroTemplate.name()][i] = macro; } } } @@ -1846,11 +1876,11 @@ void Buffer::getSourceCode(odocstream & os, pit_type par_begin, // No side effect of file copying and image conversion runparams.dryrun = true; - texrow().reset(); + d->texrow.reset(); if (full_source) { os << "% " << _("Preview source code") << "\n\n"; - texrow().newline(); - texrow().newline(); + d->texrow.newline(); + d->texrow.newline(); if (isLatex()) writeLaTeXSource(os, filePath(), runparams, true, true); else { @@ -1869,11 +1899,11 @@ void Buffer::getSourceCode(odocstream & os, pit_type par_begin, convert(par_begin), convert(par_end - 1)) << "\n\n"; - texrow().newline(); - texrow().newline(); + d->texrow.newline(); + d->texrow.newline(); // output paragraphs if (isLatex()) { - latexParagraphs(*this, paragraphs(), os, texrow(), runparams); + latexParagraphs(*this, paragraphs(), os, d->texrow, runparams); } else { // DocBook docbookParagraphs(paragraphs(), *this, os, runparams); @@ -1882,23 +1912,17 @@ void Buffer::getSourceCode(odocstream & os, pit_type par_begin, } -ErrorList const & Buffer::errorList(string const & type) const +ErrorList & Buffer::errorList(string const & type) const { - static ErrorList const emptyErrorList; - std::map::const_iterator I = pimpl_->errorLists.find(type); - if (I == pimpl_->errorLists.end()) + static ErrorList emptyErrorList; + std::map::iterator I = d->errorLists.find(type); + if (I == d->errorLists.end()) return emptyErrorList; return I->second; } -ErrorList & Buffer::errorList(string const & type) -{ - return pimpl_->errorLists[type]; -} - - void Buffer::structureChanged() const { if (gui_) @@ -1929,15 +1953,15 @@ void Buffer::setBusy(bool on) const void Buffer::setReadOnly(bool on) const { - if (gui_) - gui_->setReadOnly(on); + if (d->wa_) + d->wa_->setReadOnly(on); } void Buffer::updateTitles() const { - if (gui_) - gui_->updateTitles(); + if (d->wa_) + d->wa_->updateTitles(); } @@ -2010,7 +2034,7 @@ int AutoSaveBuffer::generateChild() // filesystems unless write of tmp_ret // failed so remove tmp file (if it // exists) - unlink(tmp_ret); + tmp_ret.removeFile(); } } else { failed = true; @@ -2083,12 +2107,10 @@ bool Buffer::writeAs(string const & newname) if (newname.empty()) { /// No argument? Ask user through dialog // FIXME UNICODE - FileDialog fileDlg(_("Choose a filename to save document as"), - LFUN_BUFFER_WRITE_AS, - make_pair(_("Documents|#o#O"), - from_utf8(lyxrc.document_path)), - make_pair(_("Templates|#T#t"), - from_utf8(lyxrc.template_path))); + FileDialog dlg(_("Choose a filename to save document as"), + LFUN_BUFFER_WRITE_AS); + dlg.setButton1(_("Documents|#o#O"), from_utf8(lyxrc.document_path)); + dlg.setButton2(_("Templates|#T#t"), from_utf8(lyxrc.template_path)); if (!support::isLyXFilename(fname)) fname += ".lyx"; @@ -2096,7 +2118,7 @@ bool Buffer::writeAs(string const & newname) support::FileFilterList const filter(_("LyX Documents (*.lyx)")); FileDialog::Result result = - fileDlg.save(from_utf8(onlyPath(fname)), + dlg.save(from_utf8(onlyPath(fname)), filter, from_utf8(onlyFilename(fname))); @@ -2172,6 +2194,22 @@ bool Buffer::menuWrite() } +void Buffer::resetChildDocuments(bool close_them) const +{ + for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) { + if (it->lyxCode() != INCLUDE_CODE) + continue; + InsetCommand const & inset = static_cast(*it); + InsetCommandParams const & ip = inset.params(); + + resetParentBuffer(this, ip, close_them); + } + + if (use_gui && masterBuffer() == this) + updateLabels(*this); +} + + void Buffer::loadChildDocuments() const { bool parse_error = false; @@ -2204,7 +2242,7 @@ string Buffer::bufferFormat() const bool Buffer::doExport(string const & format, bool put_in_tempdir, - string & result_file) + string & result_file) const { string backend_format; OutputParams runparams(¶ms().encoding()); @@ -2322,14 +2360,14 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, } -bool Buffer::doExport(string const & format, bool put_in_tempdir) +bool Buffer::doExport(string const & format, bool put_in_tempdir) const { string result_file; return doExport(format, put_in_tempdir, result_file); } -bool Buffer::preview(string const & format) +bool Buffer::preview(string const & format) const { string result_file; if (!doExport(format, true, result_file)) @@ -2433,7 +2471,7 @@ bool Buffer::readFileHelper(FileName const & s) return readFile(a); case 1: // Here we delete the autosave - unlink(a); + a.removeFile(); break; default: return false; @@ -2445,7 +2483,7 @@ bool Buffer::readFileHelper(FileName const & s) bool Buffer::loadLyXFile(FileName const & s) { - if (s.isReadable()) { + if (s.isReadableFile()) { if (readFileHelper(s)) { lyxvc().file_found_hook(s); if (!s.isWritable()) @@ -2484,13 +2522,13 @@ void Buffer::bufferErrors(TeXErrors const & terr, ErrorList & errorList) const int id_start = -1; int pos_start = -1; int errorRow = cit->error_in_line; - bool found = texrow().getIdFromRow(errorRow, id_start, + bool found = d->texrow.getIdFromRow(errorRow, id_start, pos_start); int id_end = -1; int pos_end = -1; do { ++errorRow; - found = texrow().getIdFromRow(errorRow, id_end, pos_end); + found = d->texrow.getIdFromRow(errorRow, id_end, pos_end); } while (found && id_start == id_end && pos_start == pos_end); errorList.push_back(ErrorItem(cit->error_desc,