#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"
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
-void showPrintError(string const & name)
-{
- docstring str = bformat(_("Could not print the document %1$s.\n"
- "Check that your printer is set up correctly."),
- makeDisplayPath(name, 50));
- Alert::error(_("Print document failed"), str);
-}
-
} // namespace anon
mutable TocBackend toc_backend;
/// macro tables
- typedef pair<DocIterator, MacroData> ScopeMacro;
+ struct ScopeMacro {
+ ScopeMacro() {}
+ ScopeMacro(DocIterator const & s, MacroData const & m)
+ : scope(s), macro(m) {}
+ DocIterator scope;
+ MacroData macro;
+ };
typedef map<DocIterator, ScopeMacro> PositionScopeMacroMap;
typedef map<docstring, PositionScopeMacroMap> NamePositionScopeMacroMap;
/// map from the macro name to the position map,
/// positions of child buffers in the buffer
typedef map<Buffer const * const, DocIterator> BufferPositionMap;
- typedef pair<DocIterator, Buffer const *> ScopeBuffer;
+ struct ScopeBuffer {
+ ScopeBuffer() {}
+ ScopeBuffer(DocIterator const & s,Buffer const * b)
+ : scope(s), buffer(b) {}
+ DocIterator scope;
+ Buffer const * buffer;
+ };
typedef map<DocIterator, ScopeBuffer> PositionScopeBufferMap;
/// position of children buffers in this buffer
BufferPositionMap children_positions;
/// map from children inclusion positions to their scope and their buffer
PositionScopeBufferMap position_to_children;
+ /// Contains the old buffer filePath() while saving-as, or the
+ /// directory where the document was last saved while loading.
+ string old_position;
+
+ /** Keeps track of the path of local layout files.
+ * If possible, it is always relative to the buffer path.
+ * Empty for layouts in system or user directory.
+ */
+ string layout_position;
+
/// Container for all sort of Buffer dependant errors.
map<string, ErrorList> errorLists;
/// to be updated.
mutable bool cite_labels_valid_;
+ /// These two hold the file name and format, written to by
+ /// Buffer::preview and read from by LFUN_BUFFER_VIEW_CACHE.
+ FileName preview_file_;
+ string preview_format_;
+ /// If there was an error when previewing, on the next preview we do
+ /// a fresh compile (e.g. in case the user installed a package that
+ /// was missing).
+ bool preview_error_;
+
mutable RefCache ref_cache_;
/// our Text that should be wrapped in an InsetText
/// 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<string>(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<string>(count++));
+ counter);
if (!tmpfl.createDirectory(0777)) {
throw ExceptionMessage(WarningException, _("Disk Error: "), bformat(
file_fully_loaded(false), ignore_parent(false), toc_backend(owner),
macro_lock(false), timestamp_(0), checksum_(0), wa_(0), gui_(0),
undo_(*owner), bibinfo_cache_valid_(false), bibfile_cache_valid_(false),
- cite_labels_valid_(false), preview_loader_(0),
+ cite_labels_valid_(false), inset(0), preview_loader_(0),
cloned_buffer_(cloned_buffer), clone_list_(0),
- doing_export(false), parent_buffer(0)
+ doing_export(false), parent_buffer(0),
+ word_count_(0), char_count_(0), blank_count_(0)
{
if (!cloned_buffer_) {
temppath = createBufferTmpDir();
cite_labels_valid_ = cloned_buffer_->d->cite_labels_valid_;
unnamed = cloned_buffer_->d->unnamed;
internal_buffer = cloned_buffer_->d->internal_buffer;
+ layout_position = cloned_buffer_->d->layout_position;
+ preview_file_ = cloned_buffer_->d->preview_file_;
+ preview_format_ = cloned_buffer_->d->preview_format_;
+ preview_error_ = cloned_buffer_->d->preview_error_;
}
it.paragraph().setId(cloned_it.paragraph().id());
} else
d->inset = new InsetText(this);
- d->inset->setAutoBreakRows(true);
d->inset->getText(0)->setMacrocontextPosition(par_iterator_begin());
}
for (; it != end; ++it) {
DocIterator dit = it->first.clone(buffer_clone);
dit.setBuffer(buffer_clone);
- Buffer * child = const_cast<Buffer *>(it->second.second);
+ Buffer * child = const_cast<Buffer *>(it->second.buffer);
child->cloneWithChildren(bufmap, clones);
BufferMap::iterator const bit = bufmap.find(child);
// 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();
// Also consider the master buffer log file
FileName masterfname = fname;
- LogType mtype;
+ LogType mtype = latexlog;
if (masterBuffer() != this) {
string const mlogfile = masterBuffer()->logName(&mtype);
masterfname = FileName(mlogfile);
LYXERR(Debug::PARSER, "Handling document header token: `"
<< token << '\'');
- string unknown = params().readToken(lex, token, d->filename.onlyPath());
- if (!unknown.empty()) {
- if (unknown[0] != '\\' && token == "\\textclass") {
- Alert::warning(_("Unknown document class"),
- bformat(_("Using the default document class, because the "
- "class %1$s is unknown."), from_utf8(unknown)));
+ string const result =
+ params().readToken(lex, token, d->filename.onlyPath());
+ if (!result.empty()) {
+ if (token == "\\textclass") {
+ d->layout_position = result;
} else {
++unknown_tokens;
docstring const s = bformat(_("Unknown token: "
params().indiceslist().addDefault(B_("Index"));
// read main text
+ d->old_position = originFilePath();
bool const res = text().read(lex, errorList, d->inset);
+ d->old_position.clear();
// inform parent buffer about local macros
if (parent()) {
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;
else if (success)
if (readDocument(lex))
success = false;
- if (fn.exists())
- fn.removeFile();
return success;
}
}
+bool Buffer::lastPreviewError() const
+{
+ return d->preview_error_;
+}
+
+
PreviewLoader * Buffer::loader() const
{
if (!isExporting() && lyxrc.preview == LyXRC::PREVIEW_OFF)
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"
// if the file does not yet exist, none of the backup activity
// that follows is necessary
- if (!fileName().exists())
- return writeFile(fileName());
+ if (!fileName().exists()) {
+ if (!writeFile(fileName()))
+ return false;
+ markClean();
+ return true;
+ }
// 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.
- TempFile tempfile(fileName().onlyPath(), "tmpXXXXXX.lyx");
- FileName savefile(tempfile.name());
+ string const justname = fileName().onlyFileNameWithoutExt();
+ boost::scoped_ptr<TempFile>
+ 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;
- bool const symlink = fileName().isSymLink();
+
+ FileName backupName(absFileName() + '~');
if (lyxrc.make_backup) {
- FileName backupName(absFileName() + '~');
if (!lyxrc.backupdir_path.empty()) {
string const mangledName =
subst(subst(backupName.absFileName(), '/', '!'), ':', '!');
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.
made_backup = symlink ?
}
}
+ // 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 (!symlink)
- tempfile.setAutoRemove(false);
- if (made_backup &&
- (symlink ? savefile.copyTo(fileName(), true) : savefile.moveTo(fileName()))) {
+ 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
- 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())));
+ // 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 {
+ // 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;
}
// now write out the buffer parameters.
ofs << "\\begin_header\n";
- params().writeFile(ofs);
+ params().writeFile(ofs, this);
ofs << "\\end_header\n";
// write the text
// how to check if close went ok?
// Following is an attempt... (BE 20001011)
- // good() returns false if any error occured, including some
+ // good() returns false if any error occurred, including some
// formatting error.
// bad() returns true if something bad happened in the buffer,
// which should include file system full errors.
{
OutputParams runparams = runparams_in;
- // This is necessary for LuaTeX/XeTeX with tex fonts.
- // See FIXME in BufferParams::encoding()
- if (runparams.isFullUnicode())
- runparams.encoding = encodings.fromLyXName("utf8-plain");
+ // XeTeX with TeX fonts is only safe with ASCII encoding,
+ // See #9740 and FIXME in BufferParams::encoding()
+ if (!params().useNonTeXFonts && (runparams.flavor == OutputParams::XETEX))
+ runparams.encoding = encodings.fromLyXName("ascii");
string const encoding = runparams.encoding->iconvName();
LYXERR(Debug::LATEX, "makeLaTeXFile encoding: " << encoding << ", fname=" << fname.realPath());
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."),
OutputParams runparams = runparams_in;
+ // XeTeX with TeX fonts is only safe with ASCII encoding,
+ // See #9740 and FIXME in BufferParams::encoding()
+ // FIXME: when only the current paragraph is shown, this seems to be ignored:
+ // characters encodable in the current encoding are not converted to ASCII-representation.
+ if (!params().useNonTeXFonts && (runparams.flavor == OutputParams::XETEX))
+ runparams.encoding = encodings.fromLyXName("ascii");
+
// If we are compiling a file standalone, even if this is the
// child of some other buffer, let's cut the link here, so the
// file is really independent and no concurring settings from
}
os << "\\makeatletter\n"
<< "\\def\\input@path{{"
- << docdir << "/}}\n"
+ << docdir << "}}\n"
<< "\\makeatother\n";
}
}
}
runparams_in.encoding = runparams.encoding;
- // Just to be sure. (Asger)
- os.texrow().newline();
-
- //for (int i = 0; i<d->texrow.rows(); i++) {
- // int id,pos;
- // if (d->texrow.getIdFromRow(i+1,id,pos) && id>0)
- // lyxerr << i+1 << ":" << id << ":" << getParFromID(id).paragraph().asString()<<"\n";
- //}
+ os.texrow().finalize();
LYXERR(Debug::INFO, "Finished making LaTeX file.");
LYXERR(Debug::INFO, "Row count was " << os.texrow().rows() - 1 << '.');
LaTeXFeatures features(*this, params(), runparams);
validate(features);
- d->texrow.reset();
+ d->texrow.reset(false);
DocumentClass const & tclass = params().documentClass();
- string const top_element = tclass.latexname();
+ string const & top_element = tclass.latexname();
bool const output_preamble =
output == FullSource || output == OnlyPreamble;
}
list.clear();
- Toc & toc = d->toc_backend.toc("label");
- TocIterator toc_it = toc.begin();
- TocIterator end = toc.end();
+ shared_ptr<Toc> toc = d->toc_backend.toc("label");
+ TocIterator toc_it = toc->begin();
+ TocIterator end = toc->end();
for (; toc_it != end; ++toc_it) {
if (toc_it->depth() == 0)
list.push_back(toc_it->str());
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;
enable = !isReadonly();
break;
+ case LFUN_BUFFER_VIEW_CACHE:
+ (d->preview_file_).refresh();
+ enable = (d->preview_file_).exists() && !(d->preview_file_).isFileEmpty();
+ break;
+
default:
return false;
}
// Execute the command in the background
Systemcall call;
- call.startscript(Systemcall::DontWait, command, filePath());
+ call.startscript(Systemcall::DontWait, command,
+ filePath(), layoutPos());
break;
}
bool const activate = (func.action() == LFUN_BRANCH_ACTIVATE
|| func.action() == LFUN_BRANCH_MASTER_ACTIVATE);
if (branch->isSelected() != activate) {
- buf->undo().recordUndoFullDocument(CursorData());
+ buf->undo().recordUndoBufferParams(CursorData());
branch->setSelected(activate);
dr.setError(false);
dr.screenUpdate(Update::Force);
msg += ("\n");
msg += bformat(_("Branch \"%1$s\" already exists."), branch_name);
} else {
- undo().recordUndoFullDocument(CursorData());
+ undo().recordUndoBufferParams(CursorData());
branch_list.add(branch_name);
branch = branch_list.find(branch_name);
string const x11hexname = X11hexname(branch->color());
break;
}
- case LFUN_BUFFER_PRINT: {
- // we'll assume there's a problem until we succeed
- dr.setError(true);
- string target = func.getArg(0);
- string target_name = func.getArg(1);
- string command = func.getArg(2);
-
- if (target.empty()
- || target_name.empty()
- || command.empty()) {
- LYXERR0("Unable to parse " << func.argument());
- docstring const msg =
- bformat(_("Unable to parse \"%1$s\""), func.argument());
- dr.setMessage(msg);
- break;
- }
- if (target != "printer" && target != "file") {
- LYXERR0("Unrecognized target \"" << target << '"');
- docstring const msg =
- bformat(_("Unrecognized target \"%1$s\""), from_utf8(target));
- dr.setMessage(msg);
- break;
- }
-
- if (doExport("dvi", true) != ExportSuccess) {
- showPrintError(absFileName());
- dr.setMessage(_("Error exporting to DVI."));
- break;
- }
-
- // Push directory path.
- string const path = temppath();
- // Prevent the compiler from optimizing away p
- FileName pp(path);
- PathChanger p(pp);
-
- // there are three cases here:
- // 1. we print to a file
- // 2. we print directly to a printer
- // 3. we print using a spool command (print to file first)
- Systemcall one;
- int res = 0;
- string const dviname = changeExtension(latexName(true), "dvi");
-
- if (target == "printer") {
- if (!lyxrc.print_spool_command.empty()) {
- // case 3: print using a spool
- string const psname = changeExtension(dviname,".ps");
- command += ' ' + lyxrc.print_to_file
- + quoteName(psname)
- + ' '
- + quoteName(dviname);
-
- string command2 = lyxrc.print_spool_command + ' ';
- if (target_name != "default") {
- command2 += lyxrc.print_spool_printerprefix
- + target_name
- + ' ';
- }
- command2 += quoteName(psname);
- // First run dvips.
- // If successful, then spool command
- res = one.startscript(Systemcall::Wait, command,
- filePath());
-
- if (res == 0) {
- // If there's no GUI, we have to wait on this command. Otherwise,
- // LyX deletes the temporary directory, and with it the spooled
- // file, before it can be printed!!
- Systemcall::Starttype stype = use_gui ?
- Systemcall::DontWait : Systemcall::Wait;
- res = one.startscript(stype, command2,
- filePath());
- }
- } else {
- // case 2: print directly to a printer
- if (target_name != "default")
- command += ' ' + lyxrc.print_to_printer + target_name + ' ';
- // as above....
- Systemcall::Starttype stype = use_gui ?
- Systemcall::DontWait : Systemcall::Wait;
- res = one.startscript(stype, command +
- quoteName(dviname), filePath());
- }
-
- } else {
- // case 1: print to a file
- FileName const filename(makeAbsPath(target_name, filePath()));
- FileName const dvifile(makeAbsPath(dviname, path));
- if (filename.exists()) {
- docstring text = bformat(
- _("The file %1$s already exists.\n\n"
- "Do you want to overwrite that file?"),
- makeDisplayPath(filename.absFileName()));
- if (Alert::prompt(_("Overwrite file?"),
- text, 0, 1, _("&Overwrite"), _("&Cancel")) != 0)
- break;
- }
- command += ' ' + lyxrc.print_to_file
- + quoteName(filename.toFilesystemEncoding())
- + ' '
- + quoteName(dvifile.toFilesystemEncoding());
- // as above....
- Systemcall::Starttype stype = use_gui ?
- Systemcall::DontWait : Systemcall::Wait;
- res = one.startscript(stype, command, filePath());
- }
-
- if (res == 0)
- dr.setError(false);
- else {
- dr.setMessage(_("Error running external commands."));
- showPrintError(absFileName());
- }
+ case LFUN_BUFFER_VIEW_CACHE:
+ if (!formats.view(*this, d->preview_file_,
+ d->preview_format_))
+ dr.setMessage(_("Error viewing the output file."));
break;
- }
default:
dispatched = false;
}
+string Buffer::originFilePath() const
+{
+ if (FileName::isAbsolute(params().origin))
+ return params().origin;
+
+ return filePath();
+}
+
+
+string Buffer::layoutPos() const
+{
+ return d->layout_position;
+}
+
+
+void Buffer::setLayoutPos(string const & path)
+{
+ if (path.empty()) {
+ d->layout_position.clear();
+ return;
+ }
+
+ LATTEST(FileName::isAbsolute(path));
+
+ d->layout_position =
+ to_utf8(makeRelPath(from_utf8(path), from_utf8(filePath())));
+
+ if (d->layout_position.empty())
+ d->layout_position = ".";
+}
+
+
bool Buffer::isReadonly() const
{
return d->read_only;
if (it != nameIt->second.end()) {
while (true) {
// scope ends behind pos?
- if (pos < it->second.first) {
+ if (pos < it->second.scope) {
// Looks good, remember this. If there
// is no external macro behind this,
// we found the right one already.
bestPos = it->first;
- bestData = &it->second.second;
+ bestData = &it->second.macro;
break;
}
break;
// scope ends behind pos?
- if (pos < it->second.first
+ if (pos < it->second.scope
&& (cloned_buffer_ ||
- theBufferList().isLoaded(it->second.second))) {
+ theBufferList().isLoaded(it->second.buffer))) {
// look for macro in external file
macro_lock = true;
MacroData const * data
- = it->second.second->getMacro(name, false);
+ = it->second.buffer->getMacro(name, false);
macro_lock = false;
if (data) {
bestPos = it->first;
continue;
// register macro
- // FIXME (Abdel), I don't understandt why we pass 'it' here
+ // FIXME (Abdel), I don't understand why we pass 'it' here
// instead of 'macroTemplate' defined above... is this correct?
macros[macroTemplate.name()][it] =
Impl::ScopeMacro(scope, MacroData(const_cast<Buffer *>(owner_), it));
return it->second.second;
static InsetLabel const * dummy_il = 0;
- static References const dummy_refs;
+ static References const dummy_refs = References();
it = d->ref_cache_.insert(
make_pair(label, make_pair(dummy_il, dummy_refs))).first;
return it->second.second;
}
}
-
-void Buffer::getSourceCode(odocstream & os, string const format,
+// returns NULL if id-to-row conversion is unsupported
+auto_ptr<TexRow> Buffer::getSourceCode(odocstream & os, string const & format,
pit_type par_begin, pit_type par_end,
OutputWhat output, bool master) const
{
+ auto_ptr<TexRow> texrow(NULL);
OutputParams runparams(¶ms().encoding());
runparams.nice = true;
runparams.flavor = params().getOutputFlavor(format);
setMathFlavor(runparams);
xhtmlParagraphs(text(), *this, xs, runparams);
} else if (runparams.flavor == OutputParams::TEXT) {
- bool dummy;
+ bool dummy = false;
// FIXME Handles only one paragraph, unlike the others.
// Probably should have some routine with a signature like them.
writePlaintextParagraph(*this,
LaTeXFeatures features(*this, params(), runparams);
params().validate(features);
runparams.use_polyglossia = features.usePolyglossia();
- TexRow texrow;
- texrow.reset();
- texrow.newline();
- texrow.newline();
+ texrow.reset(new TexRow());
+ texrow->newline();
+ texrow->newline();
// latex or literate
- otexstream ots(os, texrow);
+ otexstream ots(os, *texrow);
// the real stuff
latexParagraphs(*this, text(), ots, runparams);
+ texrow->finalize();
// Restore the parenthood
if (!master)
if (output == FullSource)
write(ods);
else if (output == OnlyPreamble)
- params().writeFile(ods);
+ params().writeFile(ods, this);
else if (output == OnlyBody)
text().write(ods);
os << from_utf8(ods.str());
writeDocBookSource(os, absFileName(), runparams, output);
} else {
// latex or literate
- d->texrow.reset();
- d->texrow.newline();
- d->texrow.newline();
- otexstream ots(os, d->texrow);
+ texrow.reset(new TexRow());
+ texrow->newline();
+ texrow->newline();
+ otexstream ots(os, *texrow);
if (master)
runparams.is_child = true;
writeLaTeXSource(ots, string(), runparams, output);
+ texrow->finalize();
}
}
+ return texrow;
}
// 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;
// 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
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;
}
d->cloned_buffer_->d->errorLists[error_type] = d->errorLists[error_type];
}
- if (!success)
- return ExportConverterError;
if (put_in_tempdir) {
result_file = tmp_result_file.absFileName();
- return ExportSuccess;
+ return success ? ExportSuccess : ExportConverterError;
}
if (dest_filename.empty())
formats.prettyName(format)));
}
- return ExportSuccess;
+ return success ? ExportSuccess : ExportConverterError;
}
return preview(format, update_unincluded);
}
+
Buffer::ExportStatus Buffer::preview(string const & format, bool includeall) const
{
MarkAsExporting exporting(this);
}
// (2) export with included children only
ExportStatus const status = doExport(format, true, false, result_file);
+ FileName const previewFile(result_file);
+
+ LATTEST (isClone());
+ d->cloned_buffer_->d->preview_file_ = previewFile;
+ d->cloned_buffer_->d->preview_format_ = format;
+ d->cloned_buffer_->d->preview_error_ = (status != ExportSuccess);
+
if (status != ExportSuccess)
return status;
- if (!formats.view(*this, FileName(result_file), format))
- return PreviewError;
- return PreviewSuccess;
+ if (previewFile.exists()) {
+ if (!formats.view(*this, previewFile, format))
+ return PreviewError;
+ else
+ return PreviewSuccess;
+ }
+ else {
+ // Successful export but no output file?
+ // Probably a bug in error detection.
+ LATTEST (status != ExportSuccess);
+
+ return status;
+ }
}
if (master != this) {
bufToUpdate.insert(this);
master->updateBuffer(UpdateMaster, utype);
- // If the master buffer has no gui associated with it, then the TocModel is
- // not updated during the updateBuffer call and TocModel::toc_ is invalid
- // (bug 5699). The same happens if the master buffer is open in a different
+ // If the master buffer has no gui associated with it, then the TocModel is
+ // not updated during the updateBuffer call and TocModel::toc_ is invalid
+ // (bug 5699). The same happens if the master buffer is open in a different
// window. This test catches both possibilities.
// See: http://marc.info/?l=lyx-devel&m=138590578911716&w=2
// There remains a problem here: If there is another child open in yet a third
d->bibinfo_cache_valid_ = true;
d->cite_labels_valid_ = true;
- cbuf.tocBackend().update(utype == OutputUpdate);
+ /// FIXME: Perf
+ cbuf.tocBackend().update(true, utype);
if (scope == UpdateMaster)
cbuf.structureChanged();
}
DocIterator const end = to_end ? doc_iterator_end(this) : to;
// OK, we start from here.
for (; from != end; from.forwardPos()) {
- // We are only interested in text so remove the math CursorSlice.
- while (from.inMathed()) {
+ // This skips all insets with spell check disabled.
+ while (!from.allowSpellCheck()) {
from.pop_back();
from.pos()++;
}
// If from is at the end of the document (which is possible
- // when leaving the mathed) LyX will crash later otherwise.
+ // when "from" was changed above) LyX will crash later otherwise.
if (from.atEnd() || (!to_end && from >= end))
break;
to = from;
word_lang = wl;
break;
}
-
// Do not increase progress when from == to, otherwise the word
// count will be wrong.
if (from != to) {
FileName const old_name = fileName();
FileName const old_auto = getAutosaveFileName();
bool const old_unnamed = isUnnamed();
+ bool success = true;
+ d->old_position = filePath();
setFileName(fn);
markDirty();
// are still valid.
checkChildBuffers();
checkMasterBuffer();
- return true;
} else {
// save failed
// reset the old filename and unnamed state
setFileName(old_name);
setUnnamed(old_unnamed);
- return false;
+ success = false;
}
+
+ d->old_position.clear();
+ return success;
}
-// 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
-// the InsetInclude so that it pointed to the same file. But (a) is a bit
-// complicated, because the code for this lives in GuiView.
void Buffer::checkChildBuffers()
{
Impl::BufferPositionMap::iterator it = d->children_positions.begin();
if (oldloc == newloc)
continue;
// the location of the child file is incorrect.
- Alert::warning(_("Included File Invalid"),
- bformat(_("Saving this document to a new location has made the file:\n"
- " %1$s\n"
- "inaccessible. You will need to update the included filename."),
- from_utf8(oldloc)));
cbuf->setParent(0);
inset_inc->setChildBuffer(0);
}
setParent(0);
}
+
+string Buffer::includedFilePath(string const & name, string const & ext) const
+{
+ bool isabsolute = FileName::isAbsolute(name);
+ // old_position already contains a trailing path separator
+ string const absname = isabsolute ? name : d->old_position + name;
+
+ if (d->old_position.empty()
+ || equivalent(FileName(d->old_position), FileName(filePath()))
+ || !FileName(addExtension(absname, ext)).exists())
+ return name;
+
+ if (isabsolute)
+ return to_utf8(makeRelPath(from_utf8(name), from_utf8(filePath())));
+
+ return to_utf8(makeRelPath(from_utf8(FileName(absname).realPath()),
+ from_utf8(filePath())));
+}
+
} // namespace lyx