X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=43b5ecd792f76065950c61e4439f156426260392;hb=3d4076b598deb18660e50ec9c327efc3b15f15d0;hp=9103abda0baf043599f1cd8e9d8b7df146f3d082;hpb=d2e947d585ba19852ffe3294720ca06fc2d17db1;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 9103abda0b..43b5ecd792 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -102,6 +102,7 @@ #include "support/Package.h" #include "support/PathChanger.h" #include "support/Systemcall.h" +#include "support/TempFile.h" #include "support/textutils.h" #include "support/types.h" @@ -451,13 +452,17 @@ Buffer::~Buffer() // if we're the master buffer, then we should get rid of the list // of clones if (!parent()) { - // if this is not empty, we have leaked something. worse, one of the - // children still has a reference to this list. - LASSERT(d->clone_list_->empty(), /* */); + // If this is not empty, we have leaked something. Worse, one of the + // children still has a reference to this list. But we will try to + // continue, rather than shut down. + LATTEST(d->clone_list_->empty()); list::iterator it = find(cloned_buffers.begin(), cloned_buffers.end(), d->clone_list_); - LASSERT(it != cloned_buffers.end(), /* */); - cloned_buffers.erase(it); + if (it == cloned_buffers.end()) { + // We will leak in this case, but it is safe to continue. + LATTEST(false); + } else + cloned_buffers.erase(it); delete d->clone_list_; } // FIXME Do we really need to do this right before we delete d? @@ -602,7 +607,7 @@ void Buffer::changed(bool update_metrics) const frontend::WorkAreaManager & Buffer::workAreaManager() const { - LASSERT(d->wa_, /**/); + LBUFERR(d->wa_); return *d->wa_; } @@ -978,6 +983,49 @@ bool Buffer::readDocument(Lexer & lex) } +bool Buffer::importString(string const & format, docstring const & contents, ErrorList & errorList) +{ + Format const * fmt = formats.getFormat(format); + if (!fmt) + return false; + // It is important to use the correct extension here, since some + // converters create a wrong output file otherwise (e.g. html2latex) + TempFile const tempfile("Buffer_importStringXXXXXX." + fmt->extension()); + FileName const name(tempfile.name()); + ofdocstream os(name.toFilesystemEncoding().c_str()); + bool const success = (os << contents); + os.close(); + + bool converted = false; + if (success) { + params().compressed = false; + + // remove dummy empty par + paragraphs().clear(); + + converted = importFile(format, name, errorList); + } + + if (name.exists()) + name.removeFile(); + return converted; +} + + +bool Buffer::importFile(string const & format, FileName const & name, ErrorList & errorList) +{ + if (!theConverters().isReachable(format, "lyx")) + return false; + + TempFile const tempfile("Buffer_importFileXXXXXX.lyx"); + FileName const lyx(tempfile.name()); + if (theConverters().convert(0, name, lyx, name, format, "lyx", errorList)) + return readFile(lyx) == ReadSuccess; + + return false; +} + + bool Buffer::readString(string const & s) { params().compressed = false; @@ -988,22 +1036,23 @@ bool Buffer::readString(string const & s) FileName const fn = FileName::tempName("Buffer_readString"); int file_format; - ReadStatus const ret_plf = parseLyXFormat(lex, fn, file_format); - if (ret_plf != ReadSuccess) - return ret_plf; + bool success = parseLyXFormat(lex, fn, file_format) == ReadSuccess; - if (file_format != LYX_FORMAT) { + if (success && file_format != LYX_FORMAT) { // We need to call lyx2lyx, so write the input to a file ofstream os(fn.toFilesystemEncoding().c_str()); os << s; os.close(); // lyxvc in readFile - return readFile(fn) == ReadSuccess; + if (readFile(fn) != ReadSuccess) + success = false; } - - if (readDocument(lex)) - return false; - return true; + else if (success) + if (readDocument(lex)) + success = false; + if (fn.exists()) + fn.removeFile(); + return success; } @@ -1123,7 +1172,7 @@ Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex, Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, FileName & tmpfile, int from_format) { - tmpfile = FileName::tempName("Buffer_convertLyXFormat"); + tmpfile = FileName::tempName("Buffer_convertLyXFormatXXXXXX.lyx"); if(tmpfile.empty()) { Alert::error(_("Conversion failed"), bformat(_("%1$s is from a different" @@ -1253,11 +1302,6 @@ bool Buffer::save() const bool Buffer::writeFile(FileName const & fname) const { - // FIXME Do we need to do these here? I don't think writing - // the LyX file depends upon it. (RGH) - // updateBuffer(); - // updateMacroInstances(); - if (d->read_only && fname == d->filename) return false; @@ -1941,7 +1985,7 @@ int Buffer::runChktex() if (res == -1) { Alert::error(_("chktex failure"), _("Could not run chktex successfully.")); - } else if (res > 0) { + } else { ErrorList & errlist = d->errorLists["ChkTeX"]; errlist.clear(); bufferErrors(terr, errlist); @@ -2202,57 +2246,70 @@ bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag) switch (cmd.action()) { - case LFUN_BUFFER_TOGGLE_READ_ONLY: - flag.setOnOff(isReadonly()); - break; + case LFUN_BUFFER_TOGGLE_READ_ONLY: + flag.setOnOff(isReadonly()); + break; // FIXME: There is need for a command-line import. //case LFUN_BUFFER_IMPORT: - case LFUN_BUFFER_AUTO_SAVE: - break; + case LFUN_BUFFER_AUTO_SAVE: + break; - case LFUN_BUFFER_EXPORT_CUSTOM: - // FIXME: Nothing to check here? - break; + case LFUN_BUFFER_EXPORT_CUSTOM: + // FIXME: Nothing to check here? + break; - case LFUN_BUFFER_EXPORT: { - docstring const arg = cmd.argument(); - if (arg == "custom") { - enable = true; - break; - } - string format = to_utf8(arg); - size_t pos = format.find(' '); - if (pos != string::npos) - format = format.substr(0, pos); - enable = params().isExportable(format); - if (!enable) - flag.message(bformat( - _("Don't know how to export to format: %1$s"), arg)); + case LFUN_BUFFER_EXPORT: { + docstring const arg = cmd.argument(); + if (arg == "custom") { + enable = true; break; } + string format = to_utf8(arg); + size_t pos = format.find(' '); + if (pos != string::npos) + format = format.substr(0, pos); + enable = params().isExportable(format); + if (!enable) + flag.message(bformat( + _("Don't know how to export to format: %1$s"), arg)); + break; + } - case LFUN_BUFFER_CHKTEX: - enable = params().isLatex() && !lyxrc.chktex_command.empty(); - break; + case LFUN_BUFFER_CHKTEX: + enable = params().isLatex() && !lyxrc.chktex_command.empty(); + break; - case LFUN_BUILD_PROGRAM: - enable = params().isExportable("program"); - break; + case LFUN_BUILD_PROGRAM: + enable = params().isExportable("program"); + break; - case LFUN_BRANCH_ADD: - case LFUN_BRANCHES_RENAME: - case LFUN_BUFFER_PRINT: - // if no Buffer is present, then of course we won't be called! - break; + case LFUN_BRANCH_ACTIVATE: + case LFUN_BRANCH_DEACTIVATE: + case LFUN_BRANCH_MASTER_ACTIVATE: + case LFUN_BRANCH_MASTER_DEACTIVATE: { + bool const master = (cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE + || cmd.action() == LFUN_BRANCH_MASTER_DEACTIVATE); + BranchList const & branchList = master ? masterBuffer()->params().branchlist() + : params().branchlist(); + docstring const branchName = cmd.argument(); + flag.setEnabled(!branchName.empty() && branchList.find(branchName)); + break; + } - case LFUN_BUFFER_LANGUAGE: - enable = !isReadonly(); - break; + case LFUN_BRANCH_ADD: + case LFUN_BRANCHES_RENAME: + case LFUN_BUFFER_PRINT: + // if no Buffer is present, then of course we won't be called! + break; - default: - return false; + case LFUN_BUFFER_LANGUAGE: + enable = !isReadonly(); + break; + + default: + return false; } flag.setEnabled(enable); return true; @@ -2360,6 +2417,42 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) resetAutosaveTimers(); break; + case LFUN_BRANCH_ACTIVATE: + case LFUN_BRANCH_DEACTIVATE: + case LFUN_BRANCH_MASTER_ACTIVATE: + case LFUN_BRANCH_MASTER_DEACTIVATE: { + bool const master = (func.action() == LFUN_BRANCH_MASTER_ACTIVATE + || func.action() == LFUN_BRANCH_MASTER_DEACTIVATE); + Buffer * buf = master ? const_cast(masterBuffer()) + : this; + + docstring const branch_name = func.argument(); + // the case without a branch name is handled elsewhere + if (branch_name.empty()) { + dispatched = false; + break; + } + Branch * branch = buf->params().branchlist().find(branch_name); + if (!branch) { + LYXERR0("Branch " << branch_name << " does not exist."); + dr.setError(true); + docstring const msg = + bformat(_("Branch \"%1$s\" does not exist."), branch_name); + dr.setMessage(msg); + break; + } + bool const activate = (func.action() == LFUN_BRANCH_ACTIVATE + || func.action() == LFUN_BRANCH_MASTER_ACTIVATE); + if (branch->isSelected() != activate) { + buf->undo().recordUndoFullDocument(CursorData()); + branch->setSelected(activate); + dr.setError(false); + dr.screenUpdate(Update::Force); + dr.forceBufferUpdate(); + } + break; + } + case LFUN_BRANCH_ADD: { docstring branch_name = func.argument(); if (branch_name.empty()) { @@ -2560,8 +2653,8 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr) void Buffer::changeLanguage(Language const * from, Language const * to) { - LASSERT(from, /**/); - LASSERT(to, /**/); + LASSERT(from, return); + LASSERT(to, return); for_each(par_iterator_begin(), par_iterator_end(), @@ -2672,7 +2765,7 @@ bool Buffer::isClean() const bool Buffer::isExternallyModified(CheckMethod method) const { - LASSERT(d->filename.exists(), /**/); + LASSERT(d->filename.exists(), return false); // if method == timestamp, check timestamp before checksum return (method == checksum_method || d->timestamp_ != d->filename.lastModified()) @@ -2768,11 +2861,12 @@ string Buffer::absFileName() const string Buffer::filePath() const { - int last = d->filename.onlyPath().absFileName().length() - 1; + string const abs = d->filename.onlyPath().absFileName(); + if (abs.empty()) + return abs; + int last = abs.length() - 1; - return d->filename.onlyPath().absFileName()[last] == '/' - ? d->filename.onlyPath().absFileName() - : d->filename.onlyPath().absFileName() + "/"; + return abs[last] == '/' ? abs : abs + '/'; } @@ -3318,12 +3412,9 @@ void Buffer::clearReferenceCache() const } -void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to, - InsetCode code) +void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to) { //FIXME: This does not work for child documents yet. - LASSERT(code == CITE_CODE, /**/); - reloadBibInfoCache(); // Check if the label 'from' appears more than once @@ -3341,14 +3432,12 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to, string const paramName = "key"; for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) { - if (it->lyxCode() == code) { - InsetCommand * inset = it->asInsetCommand(); - if (!inset) - continue; - docstring const oldValue = inset->getParam(paramName); - if (oldValue == from) - inset->setParam(paramName, to); - } + if (it->lyxCode() != CITE_CODE) + continue; + InsetCommand * inset = it->asInsetCommand(); + docstring const oldValue = inset->getParam(paramName); + if (oldValue == from) + inset->setParam(paramName, to); } } @@ -3684,24 +3773,6 @@ bool Buffer::autoSave() const } -// helper class, to guarantee this gets reset properly -class Buffer::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; @@ -4234,6 +4305,8 @@ void Buffer::setBuffersForInsets() const void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const { + LBUFERR(!text().paragraphs().empty()); + // Use the master text class also for child documents Buffer const * const master = masterBuffer(); DocumentClass const & textclass = master->params().documentClass(); @@ -4274,8 +4347,6 @@ void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const Buffer & cbuf = const_cast(*this); - LASSERT(!text().paragraphs().empty(), /**/); - // do the real work ParIterator parit = cbuf.par_iterator_begin(); updateBuffer(parit, utype); @@ -4347,7 +4418,7 @@ static depth_type getItemDepth(ParIterator const & it) static bool needEnumCounterReset(ParIterator const & it) { Paragraph const & par = *it; - LASSERT(par.layout().labeltype == LABEL_ENUMERATE, /**/); + LASSERT(par.layout().labeltype == LABEL_ENUMERATE, return false); depth_type const cur_depth = par.getDepth(); ParIterator prev_it = it; while (prev_it.pit()) { @@ -4500,6 +4571,7 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const { + // LASSERT: Is it safe to continue here, or should we just return? LASSERT(parit.pit() == 0, /**/); // Set the position of the text in the buffer to be able