]> git.lyx.org Git - lyx.git/blobdiff - src/Buffer.cpp
Slight re-organization.
[lyx.git] / src / Buffer.cpp
index 6dd81c49fe1651d239a5e65ac734bdce9f03c534..5ee983f301fa15870cbb88b044ff1766010cbbb3 100644 (file)
@@ -66,7 +66,6 @@
 #include "WordLangTuple.h"
 #include "WordList.h"
 
-#include "insets/InsetBibitem.h"
 #include "insets/InsetBibtex.h"
 #include "insets/InsetBranch.h"
 #include "insets/InsetInclude.h"
@@ -128,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 = 405; // vfr: author hash
+int const LYX_FORMAT = 410; // rgh: dummy format for list->labeling
 
 typedef map<string, bool> DepClean;
 typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
@@ -189,7 +188,7 @@ public:
        /// is autosave needed?
        mutable bool bak_clean;
 
-       /// is this a unnamed file (New...)?
+       /// is this an unnamed file (New...)?
        bool unnamed;
 
        /// buffer is r/o
@@ -642,10 +641,11 @@ void Buffer::setReadonly(bool const flag)
 }
 
 
-void Buffer::setFileName(string const & newfile)
+void Buffer::setFileName(FileName const & fname)
 {
-       d->filename = makeAbsPath(newfile);
+       d->filename = fname;
        setReadonly(d->filename.isReadOnly());
+       saveCheckSum();
        updateTitles();
 }
 
@@ -672,7 +672,7 @@ int Buffer::readHeader(Lexer & lex)
        params().headsep.erase();
        params().footskip.erase();
        params().columnsep.erase();
-       params().fontsCJK.erase();
+       params().fonts_cjk.erase();
        params().listings_params.clear();
        params().clearLayoutModules();
        params().clearRemovedModules();
@@ -875,7 +875,8 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn)
                return readFile(tmpFile);
        }
 
-       // InsetInfo needs to know if file is under VCS
+       // FIXME: InsetInfo needs to know whether the file is under VCS 
+       // during the parse process, so this has to be done before.
        lyxvc().file_found_hook(d->filename);
 
        if (readDocument(lex)) {
@@ -887,8 +888,8 @@ Buffer::ReadStatus Buffer::readFile(FileName const & fn)
        }
 
        d->file_fully_loaded = true;
-       d->read_only = !fname.isWritable();
-       params().compressed = fname.isZippedFile();
+       d->read_only = !d->filename.isWritable();
+       params().compressed = d->filename.isZippedFile();
        saveCheckSum();
        return ReadSuccess;
 }
@@ -986,14 +987,14 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
                if (from_format < LYX_FORMAT) {
                        Alert::error(_("Conversion script failed"),
                                bformat(_("%1$s is from an older version"
-                                       " of LyX, but the lyx2lyx script"
+                                       " of LyX and the lyx2lyx script"
                                        " failed to convert it."),
                                        from_utf8(fn.absFileName())));
                        return LyX2LyXOlderFormat;
                } else {
                        Alert::error(_("Conversion script failed"),
-                               bformat(_("%1$s is from an newer version"
-                                       " of LyX, but the lyx2lyx script"
+                               bformat(_("%1$s is from a newer version"
+                                       " of LyX and the lyx2lyx script"
                                        " failed to convert it."),
                                        from_utf8(fn.absFileName())));
                        return LyX2LyXNewerFormat;
@@ -1006,11 +1007,25 @@ Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
 // Should probably be moved to somewhere else: BufferView? GuiView?
 bool Buffer::save() const
 {
+       docstring const file = makeDisplayPath(absFileName(), 20);
+       d->filename.refresh();
+
+       // check the read-only status before moving the file as a backup
+       if (d->filename.exists()) {
+               bool const read_only = !d->filename.isWritable();
+               if (read_only) {
+                       Alert::warning(_("File is read-only"),
+                               bformat(_("The file %1$s cannot be written because it "
+                               "is marked as read-only."), file));
+                       return false;
+               }
+       }
+
        // 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);
+               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)
@@ -1111,10 +1126,10 @@ docstring Buffer::emergencyWrite()
                LYXERR0("  " << s);
                if (writeFile(FileName(s))) {
                        markClean();
-                       user_message += bformat(_("  Saved to %1$s. Phew.\n"), from_utf8(s));
+                       user_message += "  " + bformat(_("Saved to %1$s. Phew.\n"), from_utf8(s));
                        return user_message;
                } else {
-                       user_message += _("  Save failed! Trying again...\n");
+                       user_message += "  " + _("Save failed! Trying again...\n");
                }
        }
 
@@ -1124,11 +1139,11 @@ docstring Buffer::emergencyWrite()
        lyxerr << ' ' << s << endl;
        if (writeFile(FileName(s))) {
                markClean();
-               user_message += bformat(_("  Saved to %1$s. Phew.\n"), from_utf8(s));
+               user_message += "  " + bformat(_("Saved to %1$s. Phew.\n"), from_utf8(s));
                return user_message;
        }
 
-       user_message += _("  Save failed! Trying yet again...\n");
+       user_message += "  " + _("Save failed! Trying yet again...\n");
 
        // 3) In "/tmp" directory.
        // MakeAbsPath to prepend the current
@@ -1138,11 +1153,11 @@ docstring Buffer::emergencyWrite()
        lyxerr << ' ' << s << endl;
        if (writeFile(FileName(s))) {
                markClean();
-               user_message += bformat(_("  Saved to %1$s. Phew.\n"), from_utf8(s));
+               user_message += "  " + bformat(_("Saved to %1$s. Phew.\n"), from_utf8(s));
                return user_message;
        }
 
-       user_message += _("  Save failed! Bummer. Document is lost.");
+       user_message += "  " + _("Save failed! Bummer. Document is lost.");
        // Don't try again.
        markClean();
        return user_message;
@@ -1216,8 +1231,11 @@ bool Buffer::makeLaTeXFile(FileName const & fname,
                           bool output_preamble, bool output_body) const
 {
        OutputParams runparams = runparams_in;
-       if (params().useXetex)
-               runparams.flavor = OutputParams::XETEX;
+
+       // This is necessary for LuaTeX/XeTeX with tex fonts.
+       // See FIXME in BufferParams::encoding()
+       if (runparams.isFullUnicode())
+               runparams.encoding = encodings.fromLyXName("utf8-plain");
 
        string const encoding = runparams.encoding->iconvName();
        LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << "...");
@@ -1384,6 +1402,7 @@ void Buffer::writeLaTeXSource(odocstream & os,
                MacroSet parentMacros;
                listParentMacros(parentMacros, features);
 
+               runparams.use_polyglossia = features.usePolyglossia();
                // Write the preamble
                runparams.use_babel = params().writeLaTeX(os, features,
                                                          d->texrow,
@@ -1612,7 +1631,7 @@ void Buffer::writeLyXHTMLSource(odocstream & os,
 
                os << "\n<!-- Text Class Preamble -->\n"
                   << features.getTClassHTMLPreamble()
-                  << "\n<!-- Premable Snippets -->\n"
+                  << "\n<!-- Preamble Snippets -->\n"
                   << from_utf8(features.getPreambleSnippets());
 
                os << "\n<!-- Layout-provided Styles -->\n";
@@ -2024,6 +2043,7 @@ void Buffer::dispatch(FuncRequest const & func, DispatchResult & dr)
 
        case LFUN_BUFFER_AUTO_SAVE:
                autoSave();
+               resetAutosaveTimers();
                break;
 
        case LFUN_BRANCH_ADD: {
@@ -2993,22 +3013,23 @@ void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
 {
        //FIXME: This does not work for child documents yet.
        LASSERT(code == CITE_CODE, /**/);
+
        // Check if the label 'from' appears more than once
-       vector<docstring> labels;
-       string paramName;
        checkBibInfoCache();
+
        BiblioInfo const & keys = masterBibInfo();
        BiblioInfo::const_iterator bit  = keys.begin();
        BiblioInfo::const_iterator bend = keys.end();
+       vector<docstring> labels;
 
        for (; bit != bend; ++bit)
                // FIXME UNICODE
                labels.push_back(bit->first);
-       paramName = "key";
 
        if (count(labels.begin(), labels.end(), from) > 1)
                return;
 
+       string const paramName = "key";
        for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
                if (it->lyxCode() == code) {
                        InsetCommand * inset = it->asInsetCommand();
@@ -3027,7 +3048,7 @@ void Buffer::getSourceCode(odocstream & os, pit_type par_begin,
 {
        OutputParams runparams(&params().encoding());
        runparams.nice = true;
-       runparams.flavor = params().useXetex ? 
+       runparams.flavor = params().useNonTeXFonts ? 
                OutputParams::XETEX : OutputParams::LATEX;
        runparams.linelen = lyxrc.plaintext_linelen;
        // No side effect of file copying and image conversion
@@ -3269,23 +3290,36 @@ void Buffer::moveAutosaveFile(support::FileName const & oldauto) const
 }
 
 
-// Perfect target for a thread...
-void Buffer::autoSave() const
+bool Buffer::autoSave() const 
 {
-       if (d->bak_clean || isReadonly()) {
-               // We don't save now, but we'll try again later
-               resetAutosaveTimers();
-               return;
-       }
+       Buffer const * buf = d->cloned_buffer_ ? d->cloned_buffer_ : this;
+       if (buf->d->bak_clean || isReadonly())
+               return true;
 
-       // emit message signal.
        message(_("Autosaving current document..."));
-       AutoSaveBuffer autosave(*this, getAutosaveFileName());
-       autosave.start();
-
-       d->bak_clean = true;
-
-       resetAutosaveTimers();
+       buf->d->bak_clean = true;
+       
+       FileName const fname = getAutosaveFileName();
+       if (d->cloned_buffer_) {
+               // If this buffer is cloned, we assume that
+               // we are running in a separate thread already.
+               FileName const tmp_ret = FileName::tempName("lyxauto");
+               if (!tmp_ret.empty()) {
+                       writeFile(tmp_ret);
+                       // assume successful write of tmp_ret
+                       if (tmp_ret.moveTo(fname))
+                               return true;
+               }
+               // failed to write/rename tmp_ret so try writing direct
+               return writeFile(fname);
+       } else {        
+               /// This function is deprecated as the frontend needs to take care
+               /// of cloning the buffer and autosaving it in another thread. It
+               /// is still here to allow (QT_VERSION < 0x040400).
+               AutoSaveBuffer autosave(*this, fname);
+               autosave.start();
+               return true;
+       }
 }
 
 
@@ -3293,7 +3327,7 @@ string Buffer::bufferFormat() const
 {
        string format = params().documentClass().outputFormat();
        if (format == "latex") {
-               if (params().useXetex)
+               if (params().useNonTeXFonts)
                        return "xetex";
                if (params().encoding().package() == Encoding::japanese)
                        return "platex";
@@ -3304,14 +3338,14 @@ string Buffer::bufferFormat() const
 
 string Buffer::getDefaultOutputFormat() const
 {
-       if (!params().defaultOutputFormat.empty()
-           && params().defaultOutputFormat != "default")
-               return params().defaultOutputFormat;
+       if (!params().default_output_format.empty()
+           && params().default_output_format != "default")
+               return params().default_output_format;
        typedef vector<Format const *> Formats;
        Formats formats = exportableFormats(true);
        if (isDocBook()
            || isLiterate()
-           || params().useXetex
+           || params().useNonTeXFonts
            || params().encoding().package() == Encoding::japanese) {
                if (formats.empty())
                        return string();
@@ -3391,6 +3425,10 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                // FIXME: Don't hardcode format names here, but use a flag
                if (backend_format == "pdflatex")
                        runparams.flavor = OutputParams::PDFLATEX;
+               else if (backend_format == "luatex")
+                       runparams.flavor = OutputParams::LUATEX;
+               else if (backend_format == "xetex")
+                       runparams.flavor = OutputParams::XETEX;
        }
 
        string filename = latexName(false);
@@ -3421,11 +3459,10 @@ bool Buffer::doExport(string const & format, bool put_in_tempdir,
                        break;
                case BufferParams::LaTeX:
                        runparams.math_flavor = OutputParams::MathAsLaTeX; 
-                       break;                                                                                  
+                       break;
                }
-               
                makeLyXHTMLFile(FileName(filename), runparams);
-       }       else if (backend_format == "lyx")
+       } else if (backend_format == "lyx")
                writeFile(FileName(filename));
        // Docbook backend
        else if (isDocBook()) {
@@ -3597,8 +3634,12 @@ vector<string> Buffer::backends() const
        vector<string> v;
        v.push_back(bufferFormat());
        // FIXME: Don't hardcode format names here, but use a flag
-       if (v.back() == "latex")
+       if (v.back() == "latex") {
                v.push_back("pdflatex");
+               v.push_back("luatex");
+               v.push_back("xetex");
+       } else if (v.back() == "xetex")
+               v.push_back("luatex");
        v.push_back("xhtml");
        v.push_back("text");
        v.push_back("lyx");
@@ -3638,6 +3679,13 @@ Buffer::ReadStatus Buffer::loadEmergency()
                ReadStatus const ret_llf = loadThisLyXFile(emergencyFile);
                bool const success = (ret_llf == ReadSuccess);
                if (success) {
+                       if (isReadonly()) {
+                               Alert::warning(_("File is read-only"),
+                                       bformat(_("An emergency file is succesfully loaded, "
+                                       "but the original file %1$s is marked read-only. "
+                                       "Please make sure to save the document as a different "
+                                       "file."), from_utf8(d->filename.absFileName())));
+                       }
                        markDirty();
                        str = _("Document was successfully recovered.");
                } else
@@ -3693,6 +3741,14 @@ Buffer::ReadStatus Buffer::loadAutosave()
                ReadStatus const ret_llf = loadThisLyXFile(autosaveFile);
                // the file is not saved if we load the autosave file.
                if (ret_llf == ReadSuccess) {
+                       if (isReadonly()) {
+                               Alert::warning(_("File is read-only"),
+                                       bformat(_("A backup file is succesfully loaded,  "
+                                       "but the original file %1$s is marked read-only. "
+                                       "Please make sure to save the document as a "
+                                       "different file."), 
+                                       from_utf8(d->filename.absFileName())));
+                       }
                        markDirty();
                        return ReadSuccess;
                }
@@ -3923,11 +3979,11 @@ void Buffer::Impl::setLabel(ParIterator & it, UpdateType utype) const
        switch(layout.labeltype) {
        case LABEL_COUNTER:
                if (layout.toclevel <= bp.secnumdepth
-                   && (layout.latextype != LATEX_ENVIRONMENT
-                       || it.text()->isFirstInSequence(it.pit()))) {
-                       counters.step(layout.counter, utype);
-                       par.params().labelString(
-                               par.expandLabel(layout, bp));
+                     && (layout.latextype != LATEX_ENVIRONMENT
+                         || it.text()->isFirstInSequence(it.pit()))) {
+                       if (counters.hasCounter(layout.counter))
+                               counters.step(layout.counter, utype);
+                       par.params().labelString(par.expandLabel(layout, bp));
                } else
                        par.params().labelString(docstring());
                break;
@@ -4100,7 +4156,7 @@ int Buffer::spellCheck(DocIterator & from, DocIterator & to,
 Buffer::ReadStatus Buffer::reload()
 {
        setBusy(true);
-       // c.f. bug 6587
+       // c.f. bug http://www.lyx.org/trac/ticket/6587
        removeAutosaveFile();
        // e.g., read-only status could have changed due to version control
        d->filename.refresh();
@@ -4124,6 +4180,38 @@ Buffer::ReadStatus Buffer::reload()
 }
 
 
+bool Buffer::saveAs(FileName const & fn)
+{
+       FileName const old_name = fileName();
+       FileName const old_auto = getAutosaveFileName();
+       bool const old_unnamed = isUnnamed();
+
+       setFileName(fn);
+       markDirty();
+       setUnnamed(false);
+
+       if (save()) {
+               // bring the autosave file with us, just in case.
+               moveAutosaveFile(old_auto);
+               // validate version control data and
+               // correct buffer title
+               lyxvc().file_found_hook(fileName());
+               updateTitles();
+               // the file has now been saved to the new location.
+               // we need to check that the locations of child buffers
+               // are still valid.
+               checkChildBuffers();
+               return true;
+       } else {
+               // save failed
+               // reset the old filename and unnamed state
+               setFileName(old_name);
+               setUnnamed(old_unnamed);
+               return false;
+       }
+}
+
+
 // FIXME We could do better here, but it is complicated. What would be
 // nice is to offer either (a) to save the child buffer to an appropriate
 // location, so that it would "move with the master", or else (b) to update