X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=a068ecfe3a9c9e502cac0801395b4aaf56f09a83;hb=0b17cb113523fb23c43064709e9b6606fe80914c;hp=9a3d86af66fe60abe68f087507440e18d42e6098;hpb=42a2a0f289e951cc7fd4f6ef25a286f3ef400497;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 9a3d86af66..a068ecfe3a 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -72,6 +72,7 @@ #include "insets/InsetInclude.h" #include "insets/InsetText.h" +#include "mathed/InsetMathHull.h" #include "mathed/MacroTable.h" #include "mathed/MathMacroTemplate.h" #include "mathed/MathSupport.h" @@ -102,8 +103,8 @@ #include "support/textutils.h" #include "support/types.h" -#include -#include +#include "support/bind.h" +#include "support/shared_ptr.h" #include #include @@ -126,7 +127,7 @@ namespace { // Do not remove the comment below, so we get merge conflict in // independent branches. Instead add your own. -int const LYX_FORMAT = 378; // ps: rev insetinfo +int const LYX_FORMAT = 400; // uwestoehr: support for \rule typedef map DepClean; typedef map > RefCache; @@ -156,7 +157,7 @@ public: } delete inset; } - + /// search for macro in local (buffer) table or in children MacroData const * getBufferMacro(docstring const & name, DocIterator const & pos) const; @@ -254,7 +255,9 @@ public: /// A cache for bibliography info mutable BiblioInfo bibinfo_; /// whether the bibinfo cache is valid - bool bibinfo_cache_valid_; + mutable bool bibinfo_cache_valid_; + /// whether the bibfile cache is valid + mutable bool bibfile_cache_valid_; /// Cache of timestamps of .bib files map bibfile_status_; @@ -276,18 +279,27 @@ public: parent_buffer = 0; return parent_buffer; } + /// void setParent(Buffer const * pb) { - if (!cloned_buffer_ - && parent_buffer && pb && parent_buffer != pb) + if (parent_buffer == pb) + // nothing to do + return; + if (!cloned_buffer_ && parent_buffer && pb) LYXERR0("Warning: a buffer should not have two parents!"); parent_buffer = pb; + if (!cloned_buffer_ && parent_buffer) { + parent_buffer->invalidateBibfileCache(); + parent_buffer->invalidateBibinfoCache(); + } } /// If non zero, this buffer is a clone of existing buffer \p cloned_buffer_ /// This one is useful for preview detached in a thread. Buffer const * cloned_buffer_; - + /// are we in the process of exporting this buffer? + mutable bool doing_export; + private: /// So we can force access via the accessors. mutable Buffer const * parent_buffer; @@ -302,13 +314,13 @@ static FileName createBufferTmpDir() // We are in our own directory. Why bother to mangle name? // In fact I wrote this code to circumvent a problematic behaviour // (bug?) of EMX mkstemp(). - FileName tmpfl(package().temp_dir().absFilename() + "/lyx_tmpbuf" + + FileName tmpfl(package().temp_dir().absFileName() + "/lyx_tmpbuf" + convert(count++)); if (!tmpfl.createDirectory(0777)) { throw ExceptionMessage(WarningException, _("Disk Error: "), bformat( _("LyX could not create the temporary directory '%1$s' (Disk is full maybe?)"), - from_utf8(tmpfl.absFilename()))); + from_utf8(tmpfl.absFileName()))); } return tmpfl; } @@ -320,7 +332,8 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, read_only(readonly_), filename(file), file_fully_loaded(false), toc_backend(owner), macro_lock(false), timestamp_(0), checksum_(0), wa_(0), gui_(0), undo_(*owner), bibinfo_cache_valid_(false), - cloned_buffer_(cloned_buffer), parent_buffer(0) + bibfile_cache_valid_(false), cloned_buffer_(cloned_buffer), + doing_export(false), parent_buffer(0) { if (!cloned_buffer_) { temppath = createBufferTmpDir(); @@ -335,6 +348,7 @@ Buffer::Impl::Impl(Buffer * owner, FileName const & file, bool readonly_, bibfiles_cache_ = cloned_buffer_->d->bibfiles_cache_; bibinfo_ = cloned_buffer_->d->bibinfo_; bibinfo_cache_valid_ = cloned_buffer_->d->bibinfo_cache_valid_; + bibfile_cache_valid_ = cloned_buffer_->d->bibfile_cache_valid_; bibfile_status_ = cloned_buffer_->d->bibfile_status_; } @@ -399,11 +413,12 @@ Buffer::~Buffer() if (!d->cloned_buffer_ && !d->temppath.destroyDirectory()) { Alert::warning(_("Could not remove temporary directory"), bformat(_("Could not remove the temporary directory %1$s"), - from_utf8(d->temppath.absFilename()))); + from_utf8(d->temppath.absFileName()))); } // Remove any previewed LaTeX snippets associated with this buffer. - thePreviews().removeLoader(*this); + if (!isClone()) + thePreviews().removeLoader(*this); delete d; } @@ -411,7 +426,7 @@ Buffer::~Buffer() Buffer * Buffer::clone() const { - Buffer * buffer_clone = new Buffer(fileName().absFilename(), false, this); + Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this); buffer_clone->d->macro_lock = true; buffer_clone->d->children_positions.clear(); // FIXME (Abdel 09/01/2010): this is too complicated. The whole children_positions and @@ -507,7 +522,7 @@ LyXVC const & Buffer::lyxvc() const string const Buffer::temppath() const { - return d->temppath.absFilename(); + return d->temppath.absFileName(); } @@ -546,20 +561,20 @@ string Buffer::latexName(bool const no_path) const FileName latex_name = makeLatexName(d->exportFileName()); return no_path ? latex_name.onlyFileName() - : latex_name.absFilename(); + : latex_name.absFileName(); } FileName Buffer::Impl::exportFileName() const { docstring const branch_suffix = - params.branchlist().getFilenameSuffix(); + params.branchlist().getFileNameSuffix(); if (branch_suffix.empty()) return filename; string const name = filename.onlyFileNameWithoutExt() + to_utf8(branch_suffix); - FileName res(filename.onlyPath().absFilename() + "/" + name); + FileName res(filename.onlyPath().absFileName() + "/" + name); res.changeExtension(filename.extension()); return res; @@ -579,12 +594,12 @@ string Buffer::logName(LogType * type) const string const path = temppath(); FileName const fname(addName(temppath(), - onlyFilename(changeExtension(filename, + onlyFileName(changeExtension(filename, ".log")))); // FIXME: how do we know this is the name of the build log? FileName const bname( - addName(path, onlyFilename( + addName(path, onlyFileName( changeExtension(filename, formats.extension(bufferFormat()) + ".out")))); @@ -604,7 +619,7 @@ string Buffer::logName(LogType * type) const LYXERR(Debug::FILES, "Log name calculated as: " << bname); if (type) *type = buildlog; - return bname.absFilename(); + return bname.absFileName(); // If we have a newer master file log or only a master log, show this } else if (fname != masterfname && (!fname.exists() && (masterfname.exists() @@ -612,12 +627,12 @@ string Buffer::logName(LogType * type) const LYXERR(Debug::FILES, "Log name calculated as: " << masterfname); if (type) *type = mtype; - return masterfname.absFilename(); + return masterfname.absFileName(); } LYXERR(Debug::FILES, "Log name calculated as: " << fname); if (type) *type = latexlog; - return fname.absFilename(); + return fname.absFileName(); } @@ -668,6 +683,15 @@ int Buffer::readHeader(Lexer & lex) params().pdfoptions().clear(); params().indiceslist().clear(); params().backgroundcolor = lyx::rgbFromHexName("#ffffff"); + params().isbackgroundcolor = false; + params().fontcolor = lyx::rgbFromHexName("#000000"); + params().isfontcolor = false; + params().notefontcolor = lyx::rgbFromHexName("#cccccc"); + params().boxbgcolor = lyx::rgbFromHexName("#ff0000"); + params().html_latex_start.clear(); + params().html_latex_end.clear(); + params().html_math_img_scale = 1.0; + params().output_sync_macro.erase(); for (int i = 0; i < 4; ++i) { params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i]; @@ -766,7 +790,7 @@ bool Buffer::readDocument(Lexer & lex) if (!params().master.empty()) { FileName const master_file = makeAbsPath(params().master, onlyPath(absFileName())); - if (isLyXFilename(master_file.absFilename())) { + if (isLyXFileName(master_file.absFileName())) { Buffer * master = checkAndLoadLyXFile(master_file, true); if (master) { @@ -872,7 +896,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, if (!lex.checkFor("\\lyxformat")) { Alert::error(_("Document format failure"), bformat(_("%1$s is not a readable LyX document."), - from_utf8(filename.absFilename()))); + from_utf8(filename.absFileName()))); return failure; } @@ -894,7 +918,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, // Save the timestamp and checksum of disk file. If filename is an // emergency file, save the timestamp and checksum of the original lyx file // because isExternallyModified will check for this file. (BUG4193) - string diskfile = filename.absFilename(); + string diskfile = filename.absFileName(); if (suffixIs(diskfile, ".emergency")) diskfile = diskfile.substr(0, diskfile.size() - 10); saveCheckSum(FileName(diskfile)); @@ -913,7 +937,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, " version of LyX, but a temporary" " file for converting it could" " not be created."), - from_utf8(filename.absFilename()))); + from_utf8(filename.absFileName()))); return failure; } FileName const lyx2lyx = libFileSearch("lyx2lyx", "lyx2lyx"); @@ -923,7 +947,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, " version of LyX, but the" " conversion script lyx2lyx" " could not be found."), - from_utf8(filename.absFilename()))); + from_utf8(filename.absFileName()))); return failure; } ostringstream command; @@ -943,13 +967,13 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, bformat(_("%1$s is from an older version" " of LyX, but the lyx2lyx script" " failed to convert it."), - from_utf8(filename.absFilename()))); + from_utf8(filename.absFileName()))); else Alert::error(_("Conversion script failed"), bformat(_("%1$s is from a newer version" " of LyX and cannot be converted by the" " lyx2lyx script."), - from_utf8(filename.absFilename()))); + from_utf8(filename.absFileName()))); return failure; } else { bool const ret = readFile(tmpfile); @@ -963,7 +987,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, Alert::error(_("Document format failure"), bformat(_("%1$s ended unexpectedly, which means" " that it is probably corrupted."), - from_utf8(filename.absFilename()))); + from_utf8(filename.absFileName()))); return failure; } @@ -975,6 +999,17 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename, // Should probably be moved to somewhere else: BufferView? GuiView? bool Buffer::save() const { + // ask if the disk file has been externally modified (use 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); + int const ret = Alert::prompt(_("Overwrite modified file?"), + text, 1, 1, _("&Overwrite"), _("&Cancel")); + if (ret == 1) + return false; + } + // We don't need autosaves in the immediate future. (Asger) resetAutosaveTimers(); @@ -986,32 +1021,22 @@ bool Buffer::save() const backupName = FileName(absFileName() + '~'); if (!lyxrc.backupdir_path.empty()) { string const mangledName = - subst(subst(backupName.absFilename(), '/', '!'), ':', '!'); + subst(subst(backupName.absFileName(), '/', '!'), ':', '!'); backupName = FileName(addName(lyxrc.backupdir_path, mangledName)); } - if (fileName().copyTo(backupName)) { + // do not copy because of #6587 + if (fileName().moveTo(backupName)) { madeBackup = true; } 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()))); + from_utf8(backupName.absFileName()))); //LYXERR(Debug::DEBUG, "Fs error: " << fe.what()); } } - // ask if the disk file has been externally modified (use 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); - int const ret = Alert::prompt(_("Overwrite modified file?"), - text, 1, 1, _("&Overwrite"), _("&Cancel")); - if (ret == 1) - return false; - } - if (writeFile(d->filename)) { markClean(); return true; @@ -1032,7 +1057,7 @@ bool Buffer::writeFile(FileName const & fname) const bool retval = false; docstring const str = bformat(_("Saving document %1$s..."), - makeDisplayPath(fname.absFilename())); + makeDisplayPath(fname.absFileName())); message(str); string const encoded_fname = fname.toSafeFilesystemEncoding(os::CREATE); @@ -1050,7 +1075,8 @@ bool Buffer::writeFile(FileName const & fname) const return false; } - removeAutosaveFile(); + // see bug 6587 + // removeAutosaveFile(); saveCheckSum(d->filename); message(str + _(" done.")); @@ -1065,7 +1091,7 @@ docstring Buffer::emergencyWrite() if (isClean()) return docstring(); - string const doc = isUnnamed() ? onlyFilename(absFileName()) : absFileName(); + string const doc = isUnnamed() ? onlyFileName(absFileName()) : absFileName(); docstring user_message = bformat( _("LyX: Attempting to save document %1$s\n"), from_utf8(doc)); @@ -1086,7 +1112,7 @@ docstring Buffer::emergencyWrite() } // 2) In HOME directory. - string s = addName(package().home_dir().absFilename(), absFileName()); + string s = addName(package().home_dir().absFileName(), absFileName()); s += ".emergency"; lyxerr << ' ' << s << endl; if (writeFile(FileName(s))) { @@ -1100,7 +1126,7 @@ docstring Buffer::emergencyWrite() // 3) In "/tmp" directory. // MakeAbsPath to prepend the current // drive letter on OS/2 - s = addName(package().temp_dir().absFilename(), absFileName()); + s = addName(package().temp_dir().absFileName(), absFileName()); s += ".emergency"; lyxerr << ' ' << s << endl; if (writeFile(FileName(s))) { @@ -1333,7 +1359,7 @@ void Buffer::writeLaTeXSource(odocstream & os, "contains glyphs that are unknown in the\n" "current document encoding (namely %2$s).\n" "This will likely result in incomplete output.\n\n" - "Chose an appropriate document encoding (such as utf8)\n" + "Choose an appropriate document encoding (such as utf8)\n" "or change the file path name."), inputpath, uncodable_glyphs)); } else { os << "\\makeatletter\n" @@ -1411,6 +1437,12 @@ void Buffer::writeLaTeXSource(odocstream & os, // Just to be sure. (Asger) d->texrow.newline(); + //for (int i = 0; itexrow.rows(); i++) { + // int id,pos; + // if (d->texrow.getIdFromRow(i+1,id,pos) && id>0) + // lyxerr << i+1 << ":" << id << ":" << getParFromID(id).paragraph().asString()<<"\n"; + //} + LYXERR(Debug::INFO, "Finished making LaTeX file."); LYXERR(Debug::INFO, "Row count was " << d->texrow.rows() - 1 << '.'); } @@ -1444,7 +1476,7 @@ void Buffer::makeDocBookFile(FileName const & fname, if (!openFileWrite(ofs, fname)) return; - writeDocBookSource(ofs, fname.absFilename(), runparams, body_only); + writeDocBookSource(ofs, fname.absFileName(), runparams, body_only); ofs.close(); if (ofs.fail()) @@ -1552,25 +1584,29 @@ void Buffer::writeLyXHTMLSource(odocstream & os, LaTeXFeatures features(*this, params(), runparams); validate(features); updateBuffer(UpdateMaster, OutputUpdate); - checkBibInfoCache(); d->bibinfo_.makeCitationLabels(*this); updateMacros(); updateMacroInstances(); if (!only_body) { - os << "\n"; - os << "\n"; - // FIXME Language should be set properly. - os << "\n"; - os << "\n"; - // FIXME Presumably need to set this right - os << "\n"; - os << "" << features.htmlTitle() << "\n"; + os << "\n" + << "\n" + // FIXME Language should be set properly. + << "\n" + << "\n" + << "\n" + // FIXME Presumably need to set this right + << "\n"; + + docstring const & doctitle = features.htmlTitle(); + os << "" + << (doctitle.empty() ? from_ascii("LyX Document") : doctitle) + << "\n"; os << "\n\n" - << features.getTClassHTMLPreamble() - << "\n\n" - << from_utf8(features.getPreambleSnippets()); + << features.getTClassHTMLPreamble() + << "\n\n" + << from_utf8(features.getPreambleSnippets()); os << "\n\n"; docstring const styleinfo = features.getTClassHTMLStyles(); @@ -1598,7 +1634,7 @@ int Buffer::runChktex() // get LaTeX-Filename FileName const path(temppath()); - string const name = addName(path.absFilename(), latexName()); + string const name = addName(path.absFileName(), latexName()); string const org_path = filePath(); PathChanger p(path); // path to LaTeX file @@ -1612,7 +1648,7 @@ int Buffer::runChktex() makeLaTeXFile(FileName(name), org_path, runparams); TeXErrors terr; - Chktex chktex(lyxrc.chktex_command, onlyFilename(name), filePath()); + Chktex chktex(lyxrc.chktex_command, onlyFileName(name), filePath()); int const res = chktex.run(terr); // run chktex if (res == -1) { @@ -1639,7 +1675,7 @@ void Buffer::validate(LaTeXFeatures & features) const updateMacros(); for_each(paragraphs().begin(), paragraphs().end(), - boost::bind(&Paragraph::validate, _1, boost::ref(features))); + bind(&Paragraph::validate, _1, ref(features))); if (lyxerr.debugging(Debug::LATEX)) { features.showStruct(); @@ -1669,6 +1705,7 @@ void Buffer::getLabelList(vector & list) const void Buffer::updateBibfilesCache(UpdateScope scope) const { + // FIXME This is probably unnecssary, given where we call this. // If this is a child document, use the parent's cache instead. Buffer const * const pbuf = d->parent(); if (pbuf && scope != UpdateChildOnly) { @@ -1688,35 +1725,54 @@ void Buffer::updateBibfilesCache(UpdateScope scope) const } else if (it->lyxCode() == INCLUDE_CODE) { InsetInclude & inset = static_cast(*it); - inset.updateBibfilesCache(); + Buffer const * const incbuf = inset.getChildBuffer(); + if (!incbuf) + continue; support::FileNameList const & bibfiles = - inset.getBibfilesCache(); - d->bibfiles_cache_.insert(d->bibfiles_cache_.end(), - bibfiles.begin(), - bibfiles.end()); + incbuf->getBibfilesCache(UpdateChildOnly); + if (!bibfiles.empty()) { + d->bibfiles_cache_.insert(d->bibfiles_cache_.end(), + bibfiles.begin(), + bibfiles.end()); + } } } - // the bibinfo cache is now invalid + d->bibfile_cache_valid_ = true; d->bibinfo_cache_valid_ = false; } -void Buffer::invalidateBibinfoCache() +void Buffer::invalidateBibinfoCache() const { d->bibinfo_cache_valid_ = false; + // also invalidate the cache for the parent buffer + Buffer const * const pbuf = d->parent(); + if (pbuf) + pbuf->invalidateBibinfoCache(); } -support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const +void Buffer::invalidateBibfileCache() const { - // If this is a child document, use the parent's cache instead. + d->bibfile_cache_valid_ = false; + d->bibinfo_cache_valid_ = false; + // also invalidate the cache for the parent buffer Buffer const * const pbuf = d->parent(); - if (pbuf && scope != UpdateChildOnly) + if (pbuf) + pbuf->invalidateBibfileCache(); +} + + +support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const +{ + // FIXME This is probably unnecessary, given where we call this. + // If this is a child document, use the master's cache instead. + Buffer const * const pbuf = masterBuffer(); + if (pbuf != this && scope != UpdateChildOnly) return pbuf->getBibfilesCache(); - // We update the cache when first used instead of at loading time. - if (d->bibfiles_cache_.empty()) - const_cast(this)->updateBibfilesCache(scope); + if (!d->bibfile_cache_valid_) + this->updateBibfilesCache(scope); return d->bibfiles_cache_; } @@ -1724,28 +1780,28 @@ support::FileNameList const & Buffer::getBibfilesCache(UpdateScope scope) const BiblioInfo const & Buffer::masterBibInfo() const { - // if this is a child document and the parent is already loaded - // use the parent's list instead [ale990412] Buffer const * const tmp = masterBuffer(); - LASSERT(tmp, /**/); if (tmp != this) return tmp->masterBibInfo(); - return localBibInfo(); -} - - -BiblioInfo const & Buffer::localBibInfo() const -{ return d->bibinfo_; } void Buffer::checkBibInfoCache() const { - support::FileNameList const & bibfilesCache = getBibfilesCache(); + // use the master's cache + Buffer const * const tmp = masterBuffer(); + if (tmp != this) { + tmp->checkBibInfoCache(); + return; + } + + // this will also reload the cache if it is invalid + support::FileNameList const & bibfiles_cache = getBibfilesCache(); + // compare the cached timestamps with the actual ones. - support::FileNameList::const_iterator ei = bibfilesCache.begin(); - support::FileNameList::const_iterator en = bibfilesCache.end(); + support::FileNameList::const_iterator ei = bibfiles_cache.begin(); + support::FileNameList::const_iterator en = bibfiles_cache.end(); for (; ei != en; ++ ei) { time_t lastw = ei->lastModified(); time_t prevw = d->bibfile_status_[*ei]; @@ -1754,13 +1810,20 @@ void Buffer::checkBibInfoCache() const d->bibfile_status_[*ei] = lastw; } } - + + // if not valid, then reload the info if (!d->bibinfo_cache_valid_) { d->bibinfo_.clear(); - for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) - it->fillWithBibKeys(d->bibinfo_, it); + fillWithBibKeys(d->bibinfo_); d->bibinfo_cache_valid_ = true; - } + } +} + + +void Buffer::fillWithBibKeys(BiblioInfo & keys) const +{ + for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) + it->fillWithBibKeys(keys, it); } @@ -1804,7 +1867,7 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) bool enable = true; - switch (cmd.action) { + switch (cmd.action()) { case LFUN_BUFFER_TOGGLE_READ_ONLY: flag.setOnOff(isReadonly()); @@ -1876,7 +1939,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) { if (isInternal()) { // FIXME? if there is an Buffer LFUN that can be dispatched even - // if internal, put a switch '(cmd.action)' here. + // if internal, put a switch '(cmd.action())' here. dr.dispatched(false); return; } @@ -1885,7 +1948,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) bool dispatched = true; undo().beginUndoGroup(); - switch (func.action) { + switch (func.action()) { case LFUN_BUFFER_TOGGLE_READ_ONLY: if (lyxvc().inUse()) lyxvc().toggleReadOnly(); @@ -1961,28 +2024,37 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) break; case LFUN_BRANCH_ADD: { - docstring const branch_name = func.argument(); + docstring branch_name = func.argument(); if (branch_name.empty()) { dispatched = false; break; } BranchList & branch_list = params().branchlist(); - Branch * branch = branch_list.find(branch_name); - if (branch) { - LYXERR0("Branch " << branch_name << " already exists."); - dr.setError(true); - docstring const msg = - bformat(_("Branch \"%1$s\" already exists."), branch_name); - dr.setMessage(msg); - } else { - branch_list.add(branch_name); - branch = branch_list.find(branch_name); - string const x11hexname = X11hexname(branch->color()); - docstring const str = branch_name + ' ' + from_ascii(x11hexname); - lyx::dispatch(FuncRequest(LFUN_SET_COLOR, str)); - dr.setError(false); - dr.update(Update::Force); + vector const branches = + getVectorFromString(branch_name, branch_list.separator()); + docstring msg; + for (vector::const_iterator it = branches.begin(); + it != branches.end(); ++it) { + branch_name = *it; + Branch * branch = branch_list.find(branch_name); + if (branch) { + LYXERR0("Branch " << branch_name << " already exists."); + dr.setError(true); + if (!msg.empty()) + msg += ("\n"); + msg += bformat(_("Branch \"%1$s\" already exists."), branch_name); + } else { + branch_list.add(branch_name); + branch = branch_list.find(branch_name); + string const x11hexname = X11hexname(branch->color()); + docstring const str = branch_name + ' ' + from_ascii(x11hexname); + lyx::dispatch(FuncRequest(LFUN_SET_COLOR, str)); + dr.setError(false); + dr.update(Update::Force); + } } + if (!msg.empty()) + dr.setMessage(msg); break; } @@ -2003,9 +2075,10 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) bformat(_("Branch \"%1$s\" does not exist."), branchName); dr.setMessage(msg); } else { - branch->setSelected(func.action == LFUN_BRANCH_ACTIVATE); + branch->setSelected(func.action() == LFUN_BRANCH_ACTIVATE); dr.setError(false); dr.update(Update::Force); + dr.forceBufferUpdate(); } break; } @@ -2040,8 +2113,10 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) } } - if (success) + if (success) { dr.update(Update::Force); + dr.forceBufferUpdate(); + } break; } @@ -2138,7 +2213,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) docstring text = bformat( _("The file %1$s already exists.\n\n" "Do you want to overwrite that file?"), - makeDisplayPath(filename.absFilename())); + makeDisplayPath(filename.absFileName())); if (Alert::prompt(_("Overwrite file?"), text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0) break; @@ -2167,8 +2242,10 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) Language const * newL = languages.getLanguage(argument); if (!newL || oldL == newL) break; - if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual()) + if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual()) { changeLanguage(oldL, newL); + dr.forceBufferUpdate(); + } break; } @@ -2324,6 +2401,7 @@ void Buffer::markClean() const // if the .lyx file has been saved, we don't need an // autosave d->bak_clean = true; + d->undo_.markDirty(); } @@ -2374,13 +2452,13 @@ FileName Buffer::fileName() const string Buffer::absFileName() const { - return d->filename.absFilename(); + return d->filename.absFileName(); } string Buffer::filePath() const { - return d->filename.onlyPath().absFilename() + "/"; + return d->filename.onlyPath().absFileName() + "/"; } @@ -2466,18 +2544,16 @@ void Buffer::getChildren(std::vector & clist, bool grand_children) con clist.push_back(child); if (grand_children) { // there might be grandchildren - std::vector glist = child->getChildren(); - for (vector::const_iterator git = glist.begin(); - git != glist.end(); ++git) - clist.push_back(*git); + vector glist = child->getChildren(); + clist.insert(clist.end(), glist.begin(), glist.end()); } } } -std::vector Buffer::getChildren(bool grand_children) const +vector Buffer::getChildren(bool grand_children) const { - std::vector v; + vector v; getChildren(v, grand_children); return v; } @@ -2683,6 +2759,14 @@ void Buffer::Impl::updateMacros(DocIterator & it, DocIterator & scope) continue; } + if (doing_export && iit->inset->asInsetMath()) { + InsetMath * im = static_cast(iit->inset); + if (im->asHullInset()) { + InsetMathHull * hull = static_cast(im); + hull->recordLocation(it); + } + } + if (iit->inset->lyxCode() != MATHMACRO_CODE) continue; @@ -2973,11 +3057,11 @@ void Buffer::getSourceCode(odocstream & os, pit_type par_begin, ErrorList & Buffer::errorList(string const & type) const { static ErrorList emptyErrorList; - map::iterator I = d->errorLists.find(type); - if (I == d->errorLists.end()) + map::iterator it = d->errorLists.find(type); + if (it == d->errorLists.end()) return emptyErrorList; - return I->second; + return it->second; } @@ -3052,15 +3136,15 @@ public: AutoSaveBuffer(Buffer const & buffer, FileName const & fname) : buffer_(buffer), fname_(fname) {} /// - virtual boost::shared_ptr clone() const + virtual shared_ptr clone() const { - return boost::shared_ptr(new AutoSaveBuffer(*this)); + return shared_ptr(new AutoSaveBuffer(*this)); } /// int start() { command_ = to_utf8(bformat(_("Auto-saving %1$s"), - from_utf8(fname_.absFilename()))); + from_utf8(fname_.absFileName()))); return run(DontWait); } private: @@ -3126,7 +3210,7 @@ int AutoSaveBuffer::generateChild() } // namespace anon -FileName Buffer::getAutosaveFilename() const +FileName Buffer::getAutosaveFileName() const { // if the document is unnamed try to save in the backup dir, else // in the default document path, and as a last try in the filePath, @@ -3145,7 +3229,7 @@ FileName Buffer::getAutosaveFilename() const void Buffer::removeAutosaveFile() const { - FileName const f = getAutosaveFilename(); + FileName const f = getAutosaveFileName(); if (f.exists()) f.removeFile(); } @@ -3153,7 +3237,7 @@ void Buffer::removeAutosaveFile() const void Buffer::moveAutosaveFile(support::FileName const & oldauto) const { - FileName const newauto = getAutosaveFilename(); + FileName const newauto = getAutosaveFileName(); oldauto.refresh(); if (newauto != oldauto && oldauto.exists()) if (!oldauto.moveTo(newauto)) @@ -3172,7 +3256,7 @@ void Buffer::autoSave() const // emit message signal. message(_("Autosaving current document...")); - AutoSaveBuffer autosave(*this, getAutosaveFilename()); + AutoSaveBuffer autosave(*this, getAutosaveFileName()); autosave.start(); d->bak_clean = true; @@ -3214,10 +3298,41 @@ string Buffer::getDefaultOutputFormat() const } +namespace { + // helper class, to guarantee this gets reset properly + class MarkAsExporting { + public: + MarkAsExporting(Buffer const * buf) : buf_(buf) + { + LASSERT(buf_, /* */); + buf_->setExportStatus(true); + } + ~MarkAsExporting() + { + buf_->setExportStatus(false); + } + private: + Buffer const * const buf_; + }; +} + + +void Buffer::setExportStatus(bool e) const +{ + d->doing_export = e; +} + + +bool Buffer::isExporting() const +{ + return d->doing_export; +} + bool Buffer::doExport(string const & format, bool put_in_tempdir, bool includeall, string & result_file) const { + MarkAsExporting exporting(this); string backend_format; OutputParams runparams(¶ms().encoding()); runparams.flavor = OutputParams::LATEX; @@ -3270,6 +3385,21 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, // HTML backend else if (backend_format == "xhtml") { runparams.flavor = OutputParams::HTML; + switch (params().html_math_output) { + case BufferParams::MathML: + runparams.math_flavor = OutputParams::MathAsMathML; + break; + case BufferParams::HTML: + runparams.math_flavor = OutputParams::MathAsHTML; + break; + case BufferParams::Images: + runparams.math_flavor = OutputParams::MathAsImages; + break; + case BufferParams::LaTeX: + runparams.math_flavor = OutputParams::MathAsLaTeX; + break; + } + makeLyXHTMLFile(FileName(filename), runparams); } else if (backend_format == "lyx") writeFile(FileName(filename)); @@ -3302,17 +3432,26 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, bool const success = theConverters().convert(this, FileName(filename), tmp_result_file, FileName(absFileName()), backend_format, format, error_list); - // Emit the signal to show the error list. + + // Emit the signal to show the error list or copy it back to the + // cloned Buffer so that it cab be emitted afterwards. if (format != backend_format) { - errors(error_type); + if (d->cloned_buffer_) { + d->cloned_buffer_->d->errorLists[error_type] = + d->errorLists[error_type]; + } else + errors(error_type); // also to the children, in case of master-buffer-view std::vector clist = getChildren(); for (vector::const_iterator cit = clist.begin(); - cit != clist.end(); ++cit) - (*cit)->errors(error_type, true); + cit != clist.end(); ++cit) { + if (d->cloned_buffer_) { + (*cit)->d->cloned_buffer_->d->errorLists[error_type] = + (*cit)->d->errorLists[error_type]; + } else + (*cit)->errors(error_type, true); + } } - if (!success) - return false; if (d->cloned_buffer_) { // Enable reverse dvi or pdf to work by copying back the texrow @@ -3320,20 +3459,27 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, // FIXME: There is a possibility of concurrent access to texrow // here from the main GUI thread that should be securized. d->cloned_buffer_->d->texrow = d->texrow; + string const error_type = bufferFormat(); + d->cloned_buffer_->d->errorLists[error_type] = d->errorLists[error_type]; } + if (!success) + return false; + if (put_in_tempdir) { - result_file = tmp_result_file.absFilename(); + result_file = tmp_result_file.absFileName(); return true; } - result_file = changeExtension(d->exportFileName().absFilename(), ext); + result_file = changeExtension(d->exportFileName().absFileName(), ext); // We need to copy referenced files (e. g. included graphics // if format == "dvi") to the result dir. vector const files = runparams.exportdata->externalFiles(format); string const dest = onlyPath(result_file); - CopyStatus status = SUCCESS; + bool use_force = use_gui ? lyxrc.export_overwrite == ALL_FILES + : force_overwrite == ALL_FILES; + CopyStatus status = use_force ? FORCE : SUCCESS; vector::const_iterator it = files.begin(); vector::const_iterator const en = files.end(); @@ -3348,6 +3494,10 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, message(_("Document export cancelled.")); } else if (tmp_result_file.exists()) { // Finally copy the main file + use_force = use_gui ? lyxrc.export_overwrite != NO_FILES + : force_overwrite != NO_FILES; + if (status == SUCCESS && use_force) + status = FORCE; status = copyFile(format, tmp_result_file, FileName(result_file), result_file, status == FORCE); @@ -3379,6 +3529,7 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir, bool Buffer::preview(string const & format, bool includeall) const { + MarkAsExporting exporting(this); string result_file; // (1) export with all included children (omit \includeonly) if (includeall && !doExport(format, true, true)) @@ -3434,7 +3585,7 @@ bool Buffer::readFileHelper(FileName const & s) { // File information about normal file if (!s.exists()) { - docstring const file = makeDisplayPath(s.absFilename(), 50); + docstring const file = makeDisplayPath(s.absFileName(), 50); docstring text = bformat(_("The specified document\n%1$s" "\ncould not be read."), file); Alert::error(_("Could not read document"), text); @@ -3442,10 +3593,10 @@ bool Buffer::readFileHelper(FileName const & s) } // Check if emergency save file exists and is newer. - FileName const e(s.absFilename() + ".emergency"); + FileName const e(s.absFileName() + ".emergency"); if (e.exists() && s.exists() && e.lastModified() > s.lastModified()) { - docstring const file = makeDisplayPath(s.absFilename(), 20); + docstring const file = makeDisplayPath(s.absFileName(), 20); docstring const text = bformat(_("An emergency save of the document " "%1$s exists.\n\n" @@ -3465,7 +3616,7 @@ bool Buffer::readFileHelper(FileName const & s) else str = _("Document was NOT successfully recovered."); str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"), - from_utf8(e.absFilename())); + makeDisplayPath(e.absFileName())); if (!Alert::prompt(_("Delete emergency file?"), str, 1, 1, _("&Remove"), _("&Keep it"))) { @@ -3488,10 +3639,10 @@ bool Buffer::readFileHelper(FileName const & s) } // Now check if autosave file is newer. - FileName const a(onlyPath(s.absFilename()) + '#' + onlyFilename(s.absFilename()) + '#'); + FileName const a(onlyPath(s.absFileName()) + '#' + onlyFileName(s.absFileName()) + '#'); if (a.exists() && s.exists() && a.lastModified() > s.lastModified()) { - docstring const file = makeDisplayPath(s.absFilename(), 20); + docstring const file = makeDisplayPath(s.absFileName(), 20); docstring const text = bformat(_("The backup of the document " "%1$s is newer.\n\nLoad the " @@ -3573,7 +3724,7 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const DocumentClass const & textclass = master->params().documentClass(); // do this only if we are the top-level Buffer - if (scope != UpdateMaster || master == this) + if (master == this) checkBibInfoCache(); // keep the buffers to be children in this set. If the call from the @@ -3882,7 +4033,9 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, if (from == end) break; to = from; - if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) { + from.paragraph().spellCheck(); + SpellChecker::Result res = from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions); + if (SpellChecker::misspelled(res)) { word_lang = wl; break; } @@ -3901,20 +4054,26 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to, bool Buffer::reload() { setBusy(true); + // c.f. bug 6587 + removeAutosaveFile(); // e.g., read-only status could have changed due to version control d->filename.refresh(); - docstring const disp_fn = makeDisplayPath(d->filename.absFilename()); + docstring const disp_fn = makeDisplayPath(d->filename.absFileName()); bool const success = loadLyXFile(d->filename); if (success) { updateBuffer(); changed(true); + updateTitles(); markClean(); message(bformat(_("Document %1$s reloaded."), disp_fn)); } else { message(bformat(_("Could not reload document %1$s."), disp_fn)); } setBusy(false); + thePreviews().removeLoader(*this); + if (graphics::Previews::status() != LyXRC::PREVIEW_OFF) + thePreviews().generateBufferPreviews(*this); errors("Parse"); return success; } @@ -3940,7 +4099,7 @@ void Buffer::checkChildBuffers() docstring const & incfile = inset_inc->getParam("filename"); string oldloc = cbuf->absFileName(); string newloc = makeAbsPath(to_utf8(incfile), - onlyPath(absFileName())).absFilename(); + onlyPath(absFileName())).absFileName(); if (oldloc == newloc) continue; // the location of the child file is incorrect.