X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FBuffer.cpp;h=1eaa6ac224b201a172bbe3f063f470252d4c52d7;hb=0a93c9b70f861b12e27239167d9ba59ddd6ece1e;hp=51430e44a1facba642d40160862680a411e4f92e;hpb=0a6ff99f28686066675848f3410f77c0947bc357;p=lyx.git diff --git a/src/Buffer.cpp b/src/Buffer.cpp index 51430e44a1..1eaa6ac224 100644 --- a/src/Buffer.cpp +++ b/src/Buffer.cpp @@ -58,7 +58,6 @@ #include "SpellChecker.h" #include "sgml.h" #include "TexRow.h" -#include "TexStream.h" #include "Text.h" #include "TextClass.h" #include "TocBackend.h" @@ -98,6 +97,7 @@ #include "support/gzstream.h" #include "support/lstrings.h" #include "support/lyxalgo.h" +#include "support/mutex.h" #include "support/os.h" #include "support/Package.h" #include "support/PathChanger.h" @@ -354,13 +354,20 @@ private: /// Creates the per buffer temporary directory static FileName createBufferTmpDir() { - // FIXME THREAD - static int count; + // FIXME This would be the ideal application for a TempDir class (like + // TempFile but for directories) + string counter; + { + static int count; + static Mutex mutex; + Mutex::Locker locker(&mutex); + counter = convert(count++); + } // 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" + - convert(count++)); + counter); if (!tmpfl.createDirectory(0777)) { throw ExceptionMessage(WarningException, _("Disk Error: "), bformat( @@ -646,12 +653,19 @@ BufferParams const & Buffer::masterParams() const // Copy child authors to the params. We need those pointers. AuthorList const & child_authors = params().authors(); AuthorList::Authors::const_iterator it = child_authors.begin(); - for (; it != child_authors.end(); it++) + for (; it != child_authors.end(); ++it) mparams.authors().record(*it); return mparams; } +double Buffer::fontScalingFactor() const +{ + return isExporting() ? 75.0 * params().html_math_img_scale + : 0.01 * lyxrc.dpi * lyxrc.zoom * lyxrc.preview_scale_factor * params().display_pixel_ratio; +} + + ParagraphList & Buffer::paragraphs() { return text().paragraphs(); @@ -1051,7 +1065,8 @@ bool Buffer::readString(string const & s) Lexer lex; istringstream is(s); lex.setStream(is); - FileName const fn = FileName::tempName("Buffer_readString"); + TempFile tempfile("Buffer_readStringXXXXXX.lyx"); + FileName const fn = tempfile.name(); int file_format; bool success = parseLyXFormat(lex, fn, file_format) == ReadSuccess; @@ -1068,8 +1083,6 @@ bool Buffer::readString(string const & s) else if (success) if (readDocument(lex)) success = false; - if (fn.exists()) - fn.removeFile(); return success; } @@ -1190,7 +1203,9 @@ Buffer::ReadStatus Buffer::parseLyXFormat(Lexer & lex, Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn, FileName & tmpfile, int from_format) { - tmpfile = FileName::tempName("Buffer_convertLyXFormatXXXXXX.lyx"); + TempFile tempfile("Buffer_convertLyXFormatXXXXXX.lyx"); + tempfile.setAutoRemove(false); + tmpfile = tempfile.name(); if(tmpfile.empty()) { Alert::error(_("Conversion failed"), bformat(_("%1$s is from a different" @@ -1277,12 +1292,32 @@ bool Buffer::save() const // We don't need autosaves in the immediate future. (Asger) resetAutosaveTimers(); - FileName backupName; - bool madeBackup = false; + // if the file does not yet exist, none of the backup activity + // that follows is necessary + if (!fileName().exists()) + return writeFile(fileName()); + + // we first write the file to a new name, then move it to its + // proper location once that has been done successfully. that + // way we preserve the original file if something goes wrong. + string const justname = fileName().onlyFileNameWithoutExt(); + boost::scoped_ptr + tempfile(new TempFile(fileName().onlyPath(), + justname + "-XXXXXX.lyx")); + bool const symlink = fileName().isSymLink(); + if (!symlink) + tempfile->setAutoRemove(false); + + FileName savefile(tempfile->name()); + LYXERR(Debug::FILES, "Saving to " << savefile.absFileName()); + if (!writeFile(savefile)) + return false; + + // we will set this to false if we fail + bool made_backup = true; - // make a backup if the file already exists - if (lyxrc.make_backup && fileName().exists()) { - backupName = FileName(absFileName() + '~'); + FileName backupName(absFileName() + '~'); + if (lyxrc.make_backup) { if (!lyxrc.backupdir_path.empty()) { string const mangledName = subst(subst(backupName.absFileName(), '/', '!'), ':', '!'); @@ -1290,14 +1325,15 @@ bool Buffer::save() const mangledName)); } + LYXERR(Debug::FILES, "Backing up original file to " << + backupName.absFileName()); // Except file is symlink do not copy because of #6587. // Hard links have bad luck. - if (fileName().isSymLink()) - madeBackup = fileName().copyTo(backupName); - else - madeBackup = fileName().moveTo(backupName); + made_backup = symlink ? + fileName().copyTo(backupName): + fileName().moveTo(backupName); - if (!madeBackup) { + if (!made_backup) { Alert::error(_("Backup failure"), bformat(_("Cannot create backup file %1$s.\n" "Please check whether the directory exists and is writable."), @@ -1306,15 +1342,46 @@ bool Buffer::save() const } } - if (writeFile(d->filename)) { + // Destroy tempfile since it keeps the file locked on windows (bug 9234) + // Only do this if tempfile is not in autoremove mode + if (!symlink) + tempfile.reset(); + // If we have no symlink, we can simply rename the temp file. + // Otherwise, we need to copy it so the symlink stays intact. + if (made_backup && symlink ? savefile.copyTo(fileName(), true) : + savefile.moveTo(fileName())) + { + // saveCheckSum() was already called by writeFile(), but the + // time stamp is invalidated by copying/moving + saveCheckSum(); markClean(); return true; + } + // else we saved the file, but failed to move it to the right location. + + if (lyxrc.make_backup && made_backup && !symlink) { + // the original file was moved to filename.lyx~, so it will look + // to the user as if it was deleted. (see bug #9234.) we could try + // to restore it, but that would basically mean trying to do again + // what we just failed to do. better to leave things as they are. + Alert::error(_("Write failure"), + bformat(_("The file has successfully been saved as:\n %1$s.\n" + "But LyX could not move it to:\n %2$s.\n" + "Your original file has been backed up to:\n %3$s"), + from_utf8(savefile.absFileName()), + from_utf8(fileName().absFileName()), + from_utf8(backupName.absFileName()))); } else { - // Saving failed, so backup is not backup - if (madeBackup) - backupName.moveTo(d->filename); - return false; + // either we did not try to make a backup, or else we tried and failed, + // or else the original file was a symlink, in which case it was copied, + // not moved. so the original file is intact. + Alert::error(_("Write failure"), + bformat(_("Cannot move saved file to:\n %1$s.\n" + "But the file has successfully been saved as:\n %2$s."), + from_utf8(fileName().absFileName()), + from_utf8(savefile.absFileName()))); } + return false; } @@ -1501,7 +1568,6 @@ bool Buffer::makeLaTeXFile(FileName const & fname, if (!openFileWrite(ofs, fname)) return false; - //TexStream ts(ofs.rdbuf(), &texrow()); ErrorList & errorList = d->errorLists["Export"]; errorList.clear(); bool failed_export = false; @@ -1519,13 +1585,12 @@ bool Buffer::makeLaTeXFile(FileName const & fname, writeLaTeXSource(os, original_path, runparams, output); } catch (EncodingException const & e) { - odocstringstream ods; - ods.put(e.failed_char); + docstring const failed(1, e.failed_char); ostringstream oss; oss << "0x" << hex << e.failed_char << dec; docstring msg = bformat(_("Could not find LaTeX command for character '%1$s'" " (code point %2$s)"), - ods.str(), from_utf8(oss.str())); + failed, from_utf8(oss.str())); errorList.push_back(ErrorItem(msg, _("Some characters of your document are probably not " "representable in the chosen encoding.\n" "Changing the document encoding to utf8 could help."), @@ -3477,7 +3542,7 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to) } -void Buffer::getSourceCode(odocstream & os, string const format, +void Buffer::getSourceCode(odocstream & os, string const & format, pit_type par_begin, pit_type par_end, OutputWhat output, bool master) const { @@ -3712,11 +3777,13 @@ int AutoSaveBuffer::generateChild() // to fork. But we will do the save // anyway. bool failed = false; - FileName const tmp_ret = FileName::tempName("lyxauto"); + TempFile tempfile("lyxautoXXXXXX.lyx"); + tempfile.setAutoRemove(false); + FileName const tmp_ret = tempfile.name(); if (!tmp_ret.empty()) { - buffer_.writeFile(tmp_ret); - // assume successful write of tmp_ret - if (!tmp_ret.moveTo(fname_)) + if (!buffer_.writeFile(tmp_ret)) + failed = true; + else if (!tmp_ret.moveTo(fname_)) failed = true; } else failed = true; @@ -3796,7 +3863,9 @@ bool Buffer::autoSave() const // If this buffer is cloned, we assume that // we are running in a separate thread already. - FileName const tmp_ret = FileName::tempName("lyxauto"); + TempFile tempfile("lyxautoXXXXXX.lyx"); + tempfile.setAutoRemove(false); + FileName const tmp_ret = tempfile.name(); if (!tmp_ret.empty()) { writeFile(tmp_ret); // assume successful write of tmp_ret @@ -3919,7 +3988,7 @@ Buffer::ExportStatus Buffer::doExport(string const & target, bool put_in_tempdir Graph::EdgePath::const_iterator it = path.begin(); Graph::EdgePath::const_iterator en = path.end(); for (; it != en; ++it) - if (theConverters().get(*it).nice) { + if (theConverters().get(*it).nice()) { need_nice_file = true; break; } @@ -4114,6 +4183,7 @@ Buffer::ExportStatus Buffer::preview(string const & format) const return preview(format, update_unincluded); } + Buffer::ExportStatus Buffer::preview(string const & format, bool includeall) const { MarkAsExporting exporting(this);