#include "Format.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
+#include "IndicesList.h"
#include "InsetIterator.h"
#include "InsetList.h"
#include "Language.h"
#include "Lexer.h"
#include "LyXAction.h"
#include "LyX.h"
+#include "LyXFunc.h"
#include "LyXRC.h"
#include "LyXVC.h"
#include "output_docbook.h"
#include "output.h"
#include "output_latex.h"
+#include "output_xhtml.h"
#include "output_plaintext.h"
-#include "paragraph_funcs.h"
#include "Paragraph.h"
#include "ParagraphParameters.h"
#include "ParIterator.h"
#include "insets/InsetBibitem.h"
#include "insets/InsetBibtex.h"
+#include "insets/InsetBranch.h"
#include "insets/InsetInclude.h"
#include "insets/InsetText.h"
// Do not remove the comment below, so we get merge conflict in
// independent branches. Instead add your own.
-int const LYX_FORMAT = 350; // jspitzm: default output format
+int const LYX_FORMAT = 375; // jspitzm: includeonly support
typedef map<string, bool> DepClean;
typedef map<docstring, pair<InsetLabel const *, Buffer::References> > RefCache;
class Buffer::Impl
{
public:
- Impl(Buffer & parent, FileName const & file, bool readonly);
+ Impl(Buffer & parent, FileName const & file, bool readonly, Buffer const * cloned_buffer);
~Impl()
{
return parent_buffer;
}
///
- void setParent(Buffer const * pb) { parent_buffer = pb; }
+ void setParent(Buffer const * pb) {
+ if (parent_buffer && pb && parent_buffer != pb)
+ LYXERR0("Warning: a buffer should not have two parents!");
+ parent_buffer = pb;
+ }
+
+ /// 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_;
+
private:
/// So we can force access via the accessors.
mutable Buffer const * parent_buffer;
+
};
}
-Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_)
+Buffer::Impl::Impl(Buffer & parent, FileName const & file, bool readonly_,
+ Buffer const * cloned_buffer)
: lyx_clean(true), bak_clean(true), unnamed(false),
read_only(readonly_), filename(file), file_fully_loaded(false),
toc_backend(&parent), macro_lock(false), timestamp_(0),
checksum_(0), wa_(0), undo_(parent), bibinfoCacheValid_(false),
- parent_buffer(0)
+ cloned_buffer_(cloned_buffer), parent_buffer(0)
{
- temppath = createBufferTmpDir();
- lyxvc.setBuffer(&parent);
- if (use_gui)
- wa_ = new frontend::WorkAreaManager;
+ if (!cloned_buffer_) {
+ temppath = createBufferTmpDir();
+ lyxvc.setBuffer(&parent);
+ if (use_gui)
+ wa_ = new frontend::WorkAreaManager;
+ return;
+ }
+ temppath = cloned_buffer_->d->temppath;
+ file_fully_loaded = true;
+ params = cloned_buffer_->d->params;
}
-Buffer::Buffer(string const & file, bool readonly)
- : d(new Impl(*this, FileName(file), readonly)), gui_(0)
+Buffer::Buffer(string const & file, bool readonly, Buffer const * cloned_buffer)
+ : d(new Impl(*this, FileName(file), readonly, cloned_buffer)), gui_(0)
{
LYXERR(Debug::INFO, "Buffer::Buffer()");
-
- d->inset = new InsetText(*this);
+ if (cloned_buffer) {
+ d->inset = new InsetText(*cloned_buffer->d->inset);
+ d->inset->setBuffer(*this);
+ // FIXME: optimize this loop somewhat, maybe by creating a new
+ // general recursive Inset::setId().
+ DocIterator it = doc_iterator_begin(this);
+ DocIterator cloned_it = doc_iterator_begin(cloned_buffer);
+ for (; !it.atEnd(); it.forwardPar(), cloned_it.forwardPar())
+ 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());
}
// GuiView already destroyed
gui_ = 0;
- if (d->unnamed && d->filename.extension() == "internal") {
+ if (isInternal()) {
// No need to do additional cleanups for internal buffer.
delete d;
return;
theBufferList().releaseChild(this, child);
}
+ if (!isClean()) {
+ docstring msg = _("LyX attempted to close a document that had unsaved changes!\n");
+ msg += emergencyWrite();
+ Alert::warning(_("Attempting to close changed document!"), msg);
+ }
+
// clear references to children in macro tables
d->children_positions.clear();
d->position_to_children.clear();
- if (!d->temppath.destroyDirectory()) {
+ 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())));
}
-void Buffer::changed() const
+Buffer * Buffer::clone() const
+{
+ // FIXME for asynchronous export and preview: We must also clone all
+ // the child buffers!
+ return new Buffer(fileName().absFilename(), false, this);
+}
+
+
+bool Buffer::isClone() const
+{
+ return d->cloned_buffer_;
+}
+
+
+void Buffer::changed(bool update_metrics) const
{
if (d->wa_)
- d->wa_->redrawAll();
+ d->wa_->redrawAll(update_metrics);
}
string Buffer::latexName(bool const no_path) const
{
- FileName latex_name = makeLatexName(d->filename);
+ FileName latex_name =
+ makeLatexName(exportFileName());
return no_path ? latex_name.onlyFileName()
: latex_name.absFilename();
}
+FileName Buffer::exportFileName() const
+{
+ docstring const branch_suffix =
+ params().branchlist().getFilenameSuffix();
+ if (branch_suffix.empty())
+ return fileName();
+
+ string const name = fileName().onlyFileNameWithoutExt()
+ + to_utf8(branch_suffix);
+ FileName res(fileName().onlyPath().absFilename() + "/" + name);
+ res.changeExtension(fileName().extension());
+
+ return res;
+}
+
+
string Buffer::logName(LogType * type) const
{
string const filename = latexName(false);
FileName const fname(addName(temppath(),
onlyFilename(changeExtension(filename,
".log"))));
+
+ // FIXME: how do we know this is the name of the build log?
FileName const bname(
addName(path, onlyFilename(
changeExtension(filename,
- formats.extension("literate") + ".out"))));
+ formats.extension(bufferFormat()) + ".out"))));
- // If no Latex log or Build log is newer, show Build log
+ // Also consider the master buffer log file
+ FileName masterfname = fname;
+ LogType mtype;
+ if (masterBuffer() != this) {
+ string const mlogfile = masterBuffer()->logName(&mtype);
+ masterfname = FileName(mlogfile);
+ }
+ // If no Latex log or Build log is newer, show Build log
if (bname.exists() &&
- (!fname.exists() || fname.lastModified() < bname.lastModified())) {
+ ((!fname.exists() && !masterfname.exists())
+ || (fname.lastModified() < bname.lastModified()
+ && masterfname.lastModified() < bname.lastModified()))) {
LYXERR(Debug::FILES, "Log name calculated as: " << bname);
if (type)
*type = buildlog;
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()
+ || fname.lastModified() < masterfname.lastModified()))) {
+ LYXERR(Debug::FILES, "Log name calculated as: " << masterfname);
+ if (type)
+ *type = mtype;
+ return masterfname.absFilename();
}
LYXERR(Debug::FILES, "Log name calculated as: " << fname);
if (type)
params().listings_params.clear();
params().clearLayoutModules();
params().clearRemovedModules();
+ params().clearIncludedChildren();
params().pdfoptions().clear();
+ params().indiceslist().clear();
+ params().backgroundcolor = lyx::rgbFromHexName("#ffffff");
for (int i = 0; i < 4; ++i) {
params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i];
}
}
}
+
+ // assure we have a default index
+ params().indiceslist().addDefault(B_("Index"));
// read main text
- bool const res = text().read(*this, lex, errorList, d->inset);
+ bool const res = text().read(lex, errorList, d->inset);
+ usermacros.clear();
updateMacros();
updateMacroInstances();
return res;
}
-// needed to insert the selection
-void Buffer::insertStringAsLines(ParagraphList & pars,
- pit_type & pit, pos_type & pos,
- Font const & fn, docstring const & str, bool autobreakrows)
-{
- Font font = fn;
-
- // insert the string, don't insert doublespace
- bool space_inserted = true;
- for (docstring::const_iterator cit = str.begin();
- cit != str.end(); ++cit) {
- Paragraph & par = pars[pit];
- if (*cit == '\n') {
- if (autobreakrows && (!par.empty() || par.allowEmpty())) {
- breakParagraph(params(), pars, pit, pos,
- par.layout().isEnvironment());
- ++pit;
- pos = 0;
- space_inserted = true;
- } else {
- continue;
- }
- // do not insert consecutive spaces if !free_spacing
- } else if ((*cit == ' ' || *cit == '\t') &&
- space_inserted && !par.isFreeSpacing()) {
- continue;
- } else if (*cit == '\t') {
- if (!par.isFreeSpacing()) {
- // tabs are like spaces here
- par.insertChar(pos, ' ', font, params().trackChanges);
- ++pos;
- space_inserted = true;
- } else {
- par.insertChar(pos, *cit, font, params().trackChanges);
- ++pos;
- space_inserted = true;
- }
- } else if (!isPrintable(*cit)) {
- // Ignore unprintables
- continue;
- } else {
- // just insert the character
- par.insertChar(pos, *cit, font, params().trackChanges);
- ++pos;
- space_inserted = (*cit == ' ');
- }
-
- }
-}
-
-
bool Buffer::readString(string const & s)
{
params().compressed = false;
}
+docstring Buffer::emergencyWrite()
+{
+ // No need to save if the buffer has not changed.
+ if (isClean())
+ return docstring();
+
+ string const doc = isUnnamed() ? onlyFilename(absFileName()) : absFileName();
+
+ docstring user_message = bformat(
+ _("LyX: Attempting to save document %1$s\n"), from_utf8(doc));
+
+ // We try to save three places:
+ // 1) Same place as document. Unless it is an unnamed doc.
+ if (!isUnnamed()) {
+ string s = absFileName();
+ s += ".emergency";
+ LYXERR0(" " << s);
+ if (writeFile(FileName(s))) {
+ markClean();
+ user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ return user_message;
+ } else {
+ user_message += _(" Save failed! Trying again...\n");
+ }
+ }
+
+ // 2) In HOME directory.
+ string s = addName(package().home_dir().absFilename(), absFileName());
+ s += ".emergency";
+ lyxerr << ' ' << s << endl;
+ if (writeFile(FileName(s))) {
+ markClean();
+ user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ return user_message;
+ }
+
+ user_message += _(" Save failed! Trying yet again...\n");
+
+ // 3) In "/tmp" directory.
+ // MakeAbsPath to prepend the current
+ // drive letter on OS/2
+ s = addName(package().temp_dir().absFilename(), absFileName());
+ s += ".emergency";
+ lyxerr << ' ' << s << endl;
+ if (writeFile(FileName(s))) {
+ markClean();
+ user_message += bformat(_(" Saved to %1$s. Phew.\n"), from_utf8(s));
+ return user_message;
+ }
+
+ user_message += _(" Save failed! Bummer. Document is lost.");
+ // Don't try again.
+ markClean();
+ return user_message;
+}
+
+
bool Buffer::write(ostream & ofs) const
{
#ifdef HAVE_LOCALE
AuthorList::Authors::const_iterator a_it = params().authors().begin();
AuthorList::Authors::const_iterator a_end = params().authors().end();
for (; a_it != a_end; ++a_it)
- a_it->second.setUsed(false);
+ a_it->setUsed(false);
ParIterator const end = const_cast<Buffer *>(this)->par_iterator_end();
ParIterator it = const_cast<Buffer *>(this)->par_iterator_begin();
// write the text
ofs << "\n\\begin_body\n";
- text().write(*this, ofs);
+ text().write(ofs);
ofs << "\n\\end_body\n";
// Write marker that shows file is complete
listParentMacros(parentMacros, features);
// Write the preamble
- runparams.use_babel = params().writeLaTeX(os, features, d->texrow);
+ runparams.use_babel = params().writeLaTeX(os, features,
+ d->texrow,
+ d->filename.onlyPath());
runparams.use_japanese = features.isRequired("japanese");
sgml::openTag(os, top);
os << '\n';
- docbookParagraphs(paragraphs(), *this, os, runparams);
+ docbookParagraphs(text(), *this, os, runparams);
sgml::closeTag(os, top_element);
}
+void Buffer::makeLyXHTMLFile(FileName const & fname,
+ OutputParams const & runparams,
+ bool const body_only) const
+{
+ LYXERR(Debug::LATEX, "makeLyXHTMLFile...");
+
+ ofdocstream ofs;
+ if (!openFileWrite(ofs, fname))
+ return;
+
+ writeLyXHTMLSource(ofs, runparams, body_only);
+
+ ofs.close();
+ if (ofs.fail())
+ lyxerr << "File '" << fname << "' was not closed properly." << endl;
+}
+
+
+void Buffer::writeLyXHTMLSource(odocstream & os,
+ OutputParams const & runparams,
+ bool const only_body) const
+{
+ LaTeXFeatures features(*this, params(), runparams);
+ validate(features);
+ updateLabels(UpdateMaster, true);
+ checkBibInfoCache();
+ d->bibinfo_.collectCitedEntries(*this);
+
+ if (!only_body) {
+ os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN\" \"http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd\">\n";
+ // FIXME Language should be set properly.
+ os << "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n";
+ // FIXME Header
+ os << "<head>\n";
+ // FIXME Presumably need to set this right
+ os << "<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n";
+ // FIXME Get this during validation? What about other meta-data?
+ os << "<title>TBA</title>\n";
+
+ os << "\n<!-- Text Class Preamble -->\n"
+ << features.getTClassHTMLPreamble()
+ << "\n<!-- Premable Snippets -->\n"
+ << from_utf8(features.getPreambleSnippets());
+
+ os << "\n<!-- Layout-provided Styles -->\n";
+ docstring const styleinfo = features.getTClassHTMLStyles();
+ if (!styleinfo.empty()) {
+ os << "<style type='text/css'>\n"
+ << styleinfo
+ << "</style>\n";
+ }
+ os << "</head>\n<body>\n";
+ }
+
+ XHTMLStream xs(os);
+ params().documentClass().counters().reset();
+ xhtmlParagraphs(text(), *this, xs, runparams);
+ if (!only_body)
+ os << "</body>\n</html>\n";
+}
+
+
// chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
// Other flags: -wall -v0 -x
int Buffer::runChktex()
BiblioInfo const & Buffer::localBibInfo() const
{
- if (d->bibinfoCacheValid_) {
- support::FileNameList const & bibfilesCache = getBibfilesCache();
- // compare the cached timestamps with the actual ones.
- support::FileNameList::const_iterator ei = bibfilesCache.begin();
- support::FileNameList::const_iterator en = bibfilesCache.end();
- for (; ei != en; ++ ei) {
- time_t lastw = ei->lastModified();
- if (lastw != d->bibfileStatus_[*ei]) {
- d->bibinfoCacheValid_ = false;
- d->bibfileStatus_[*ei] = lastw;
- break;
- }
+ checkBibInfoCache();
+ return d->bibinfo_;
+}
+
+
+void Buffer::checkBibInfoCache() const
+{
+ support::FileNameList const & bibfilesCache = getBibfilesCache();
+ // compare the cached timestamps with the actual ones.
+ support::FileNameList::const_iterator ei = bibfilesCache.begin();
+ support::FileNameList::const_iterator en = bibfilesCache.end();
+ for (; ei != en; ++ ei) {
+ time_t lastw = ei->lastModified();
+ time_t prevw = d->bibfileStatus_[*ei];
+ if (lastw != prevw) {
+ d->bibinfoCacheValid_ = false;
+ d->bibfileStatus_[*ei] = lastw;
}
}
for (InsetIterator it = inset_iterator_begin(inset()); it; ++it)
it->fillWithBibKeys(d->bibinfo_, it);
d->bibinfoCacheValid_ = true;
- }
- return d->bibinfo_;
+ }
}
}
+bool Buffer::isExportableFormat(string const & format) const
+{
+ typedef vector<Format const *> Formats;
+ Formats formats;
+ formats = exportableFormats(true);
+ Formats::const_iterator fit = formats.begin();
+ Formats::const_iterator end = formats.end();
+ for (; fit != end ; ++fit) {
+ if ((*fit)->name() == format)
+ return true;
+ }
+ return false;
+}
+
+
bool Buffer::getStatus(FuncRequest const & cmd, FuncStatus & flag)
{
+ if (isInternal()) {
+ // FIXME? if there is an Buffer LFUN that can be dispatched even
+ // if internal, put a switch '(cmd.action)' here.
+ return false;
+ }
+
+ bool enable = true;
+
switch (cmd.action) {
+
+ 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_EXPORT_CUSTOM:
+ // FIXME: Nothing to check here?
+ break;
+
case LFUN_BUFFER_EXPORT: {
docstring const arg = cmd.argument();
- bool enable = arg == "custom" || isExportable(to_utf8(arg));
+ enable = arg == "custom" || isExportable(to_utf8(arg));
if (!enable)
flag.message(bformat(
_("Don't know how to export to format: %1$s"), arg));
- flag.setEnabled(enable);
break;
}
+ case LFUN_BUFFER_CHKTEX:
+ enable = isLatex() && !lyxrc.chktex_command.empty();
+ break;
+
+ case LFUN_BUILD_PROGRAM:
+ enable = isExportable("program");
+ break;
+
case LFUN_BRANCH_ACTIVATE:
case LFUN_BRANCH_DEACTIVATE: {
- BranchList const & branchList = params().branchlist();
- docstring const branchName = cmd.argument();
- flag.setEnabled(!branchName.empty()
- && branchList.find(branchName));
+ BranchList const & branchList = params().branchlist();
+ docstring const branchName = cmd.argument();
+ enable = !branchName.empty() && branchList.find(branchName);
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!
- flag.setEnabled(true);
+ break;
+
+ case LFUN_BUFFER_LANGUAGE:
+ enable = !isReadonly();
break;
default:
return false;
}
+ flag.setEnabled(enable);
return true;
}
// whether we have a GUI or not. The boolean use_gui holds this information.
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.
+ dr.dispatched(false);
+ return;
+ }
+ string const argument = to_utf8(func.argument());
// We'll set this back to false if need be.
bool dispatched = true;
+ undo().beginUndoGroup();
switch (func.action) {
- case LFUN_BUFFER_EXPORT: {
- bool success = doExport(to_utf8(func.argument()), false);
- dr.setError(success);
- if (!success)
- dr.setMessage(bformat(_("Error exporting to format: %1$s."),
- func.argument()));
+ case LFUN_BUFFER_TOGGLE_READ_ONLY:
+ if (lyxvc().inUse())
+ lyxvc().toggleReadOnly();
+ else
+ setReadonly(!isReadonly());
+ break;
+
+ case LFUN_BUFFER_EXPORT: {
+ bool success = doExport(argument, false);
+ dr.setError(success);
+ if (!success)
+ dr.setMessage(bformat(_("Error exporting to format: %1$s."),
+ func.argument()));
+ break;
+ }
+
+ case LFUN_BUILD_PROGRAM:
+ doExport("program", true);
+ break;
+
+ case LFUN_BUFFER_CHKTEX:
+ runChktex();
+ break;
+
+ case LFUN_BUFFER_EXPORT_CUSTOM: {
+ string format_name;
+ string command = split(argument, format_name, ' ');
+ Format const * format = formats.getFormat(format_name);
+ if (!format) {
+ lyxerr << "Format \"" << format_name
+ << "\" not recognized!"
+ << endl;
break;
}
- case LFUN_BRANCH_ACTIVATE:
- case LFUN_BRANCH_DEACTIVATE: {
- BranchList & branchList = params().branchlist();
- docstring const branchName = func.argument();
- // the case without a branch name is handled elsewhere
- if (branchName.empty()) {
- dispatched = false;
+ // The name of the file created by the conversion process
+ string filename;
+
+ // Output to filename
+ if (format->name() == "lyx") {
+ string const latexname = latexName(false);
+ filename = changeExtension(latexname,
+ format->extension());
+ filename = addName(temppath(), filename);
+
+ if (!writeFile(FileName(filename)))
break;
- }
- Branch * branch = branchList.find(branchName);
- if (!branch) {
- LYXERR0("Branch " << branchName << " does not exist.");
- dr.setError(true);
- docstring const msg =
- bformat(_("Branch \"%1$s\" does not exist."), branchName);
- dr.setMessage(msg);
- } else {
- branch->setSelected(func.action == LFUN_BRANCH_ACTIVATE);
- dr.setError(false);
- dr.update(Update::Force);
- }
+
+ } else {
+ doExport(format_name, true, filename);
+ }
+
+ // Substitute $$FName for filename
+ if (!contains(command, "$$FName"))
+ command = "( " + command + " ) < $$FName";
+ command = subst(command, "$$FName", filename);
+
+ // Execute the command in the background
+ Systemcall call;
+ call.startscript(Systemcall::DontWait, command);
+ break;
+ }
+
+ // FIXME: There is need for a command-line import.
+ /*
+ case LFUN_BUFFER_IMPORT:
+ doImport(argument);
+ break;
+ */
+
+ case LFUN_BUFFER_AUTO_SAVE:
+ autoSave();
+ break;
+
+ case LFUN_BRANCH_ADD: {
+ docstring const 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);
+ }
+ 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;
+ case LFUN_BRANCH_ACTIVATE:
+ case LFUN_BRANCH_DEACTIVATE: {
+ BranchList & branchList = params().branchlist();
+ docstring const branchName = func.argument();
+ // the case without a branch name is handled elsewhere
+ if (branchName.empty()) {
+ dispatched = false;
+ break;
+ }
+ Branch * branch = branchList.find(branchName);
+ if (!branch) {
+ LYXERR0("Branch " << branchName << " does not exist.");
+ dr.setError(true);
+ docstring const msg =
+ bformat(_("Branch \"%1$s\" does not exist."), branchName);
+ dr.setMessage(msg);
+ } else {
+ branch->setSelected(func.action == LFUN_BRANCH_ACTIVATE);
+ dr.setError(false);
+ dr.update(Update::Force);
+ }
+ break;
+ }
+
+ case LFUN_BRANCHES_RENAME: {
+ if (func.argument().empty())
+ break;
+
+ docstring const oldname = from_utf8(func.getArg(0));
+ docstring const newname = from_utf8(func.getArg(1));
+ InsetIterator it = inset_iterator_begin(inset());
+ InsetIterator const end = inset_iterator_end(inset());
+ bool success = false;
+ for (; it != end; ++it) {
+ if (it->lyxCode() == BRANCH_CODE) {
+ InsetBranch & ins = static_cast<InsetBranch &>(*it);
+ if (ins.branch() == oldname) {
+ undo().recordUndo(it);
+ ins.rename(newname);
+ success = true;
+ continue;
+ }
}
- 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 (it->lyxCode() == INCLUDE_CODE) {
+ // get buffer of external file
+ InsetInclude const & ins =
+ static_cast<InsetInclude const &>(*it);
+ Buffer * child = ins.getChildBuffer();
+ if (!child)
+ continue;
+ child->dispatch(func, dr);
}
+ }
- if (!doExport("dvi", true)) {
- showPrintError(absFileName());
- dr.setMessage(_("Error exporting to DVI."));
- break;
- }
+ if (success)
+ dr.update(Update::Force);
+ 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;
+ }
- // 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);
-
- 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);
- }
- } else {
- // case 2: print directly to a printer
- if (target_name != "default")
- command += ' ' + lyxrc.print_to_printer + target_name + ' ';
- // as above....
+ if (!doExport("dvi", true)) {
+ 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);
+
+ 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, command + quoteName(dviname));
+ res = one.startscript(stype, command2);
}
-
} 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());
+ // 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);
+ res = one.startscript(stype, command + quoteName(dviname));
}
- if (res == 0)
- dr.setError(false);
- else {
- dr.setMessage(_("Error running external commands."));
- showPrintError(absFileName());
+ } 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;
}
- 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);
}
- default:
- dispatched = false;
+ if (res == 0)
+ dr.setError(false);
+ else {
+ dr.setMessage(_("Error running external commands."));
+ showPrintError(absFileName());
+ }
+ break;
+ }
+
+ case LFUN_BUFFER_LANGUAGE: {
+ Language const * oldL = params().language;
+ Language const * newL = languages.getLanguage(argument);
+ if (!newL || oldL == newL)
break;
+ if (oldL->rightToLeft() == newL->rightToLeft() && !isMultiLingual())
+ changeLanguage(oldL, newL);
+ break;
+ }
+
+ default:
+ dispatched = false;
+ break;
}
dr.dispatched(dispatched);
+ undo().endUndoGroup();
}
}
-// FIXME: this function should be moved to buffer_pimpl.C
+/// \note
+/// Don't check unnamed, here: isInternal() is used in
+/// newBuffer(), where the unnamed flag has not been set by anyone
+/// yet. Also, for an internal buffer, there should be no need for
+/// retrieving fileName() nor for checking if it is unnamed or not.
+bool Buffer::isInternal() const
+{
+ return fileName().extension() == "internal";
+}
+
+
void Buffer::markDirty()
{
if (d->lyx_clean) {
}
-std::vector<Buffer *> Buffer::getChildren() const
+void Buffer::getChildren(std::vector<Buffer *> & clist, bool grand_children) const
{
- std::vector<Buffer *> clist;
// loop over children
Impl::BufferPositionMap::iterator it = d->children_positions.begin();
Impl::BufferPositionMap::iterator end = d->children_positions.end();
for (; it != end; ++it) {
Buffer * child = const_cast<Buffer *>(it->first);
clist.push_back(child);
- // there might be grandchildren
- std::vector<Buffer *> glist = child->getChildren();
- for (vector<Buffer *>::const_iterator git = glist.begin();
- git != glist.end(); ++git)
- clist.push_back(*git);
+ if (grand_children) {
+ // there might be grandchildren
+ std::vector<Buffer *> glist = child->getChildren();
+ for (vector<Buffer *>::const_iterator git = glist.begin();
+ git != glist.end(); ++git)
+ clist.push_back(*git);
+ }
}
- return clist;
+}
+
+
+std::vector<Buffer *> Buffer::getChildren(bool grand_children) const
+{
+ std::vector<Buffer *> v;
+ getChildren(v, grand_children);
+ return v;
}
// get macro data
MathMacroTemplate & macroTemplate =
static_cast<MathMacroTemplate &>(*iit->inset);
- MacroContext mc(*this, it);
+ MacroContext mc(this, it);
macroTemplate.updateToContext(mc);
// valid?
continue;
// register macro
+ // FIXME (Abdel), I don't understandt why we pass 'it' here
+ // instead of 'macroTemplate' defined above... is this correct?
d->macros[macroTemplate.name()][it] =
- Impl::ScopeMacro(scope, MacroData(*this, it));
+ Impl::ScopeMacro(scope, MacroData(const_cast<Buffer *>(this), it));
}
// next paragraph
}
+void Buffer::getUsedBranches(std::list<docstring> & result, bool const from_master) const
+{
+ InsetIterator it = inset_iterator_begin(inset());
+ InsetIterator const end = inset_iterator_end(inset());
+ for (; it != end; ++it) {
+ if (it->lyxCode() == BRANCH_CODE) {
+ InsetBranch & br = static_cast<InsetBranch &>(*it);
+ docstring const name = br.branch();
+ if (!from_master && !params().branchlist().find(name))
+ result.push_back(name);
+ else if (from_master && !masterBuffer()->params().branchlist().find(name))
+ result.push_back(name);
+ continue;
+ }
+ if (it->lyxCode() == INCLUDE_CODE) {
+ // get buffer of external file
+ InsetInclude const & ins =
+ static_cast<InsetInclude const &>(*it);
+ Buffer * child = ins.getChildBuffer();
+ if (!child)
+ continue;
+ child->getUsedBranches(result, true);
+ }
+ }
+ // remove duplicates
+ result.unique();
+}
+
+
void Buffer::updateMacroInstances() const
{
LYXERR(Debug::MACROS, "updateMacroInstances for "
<< d->filename.onlyFileName());
DocIterator it = doc_iterator_begin(this);
- DocIterator end = doc_iterator_end(this);
- for (; it != end; it.forwardPos()) {
- // look for MathData cells in InsetMathNest insets
- Inset * inset = it.nextInset();
- if (!inset)
- continue;
-
- InsetMath * minset = inset->asInsetMath();
+ it.forwardInset();
+ DocIterator const end = doc_iterator_end(this);
+ for (; it != end; it.forwardInset()) {
+ // look for MathData cells in InsetMathNest insets
+ InsetMath * minset = it.nextInset()->asInsetMath();
if (!minset)
continue;
// update macro in all cells of the InsetMathNest
DocIterator::idx_type n = minset->nargs();
- MacroContext mc = MacroContext(*this, it);
+ MacroContext mc = MacroContext(this, it);
for (DocIterator::idx_type i = 0; i < n; ++i) {
MathData & data = minset->cell(i);
data.updateMacros(0, mc);
// No side effect of file copying and image conversion
runparams.dryrun = true;
- d->texrow.reset();
if (full_source) {
os << "% " << _("Preview source code") << "\n\n";
+ d->texrow.reset();
d->texrow.newline();
d->texrow.newline();
if (isDocBook())
convert<docstring>(par_end - 1))
<< "\n\n";
}
- d->texrow.newline();
- d->texrow.newline();
+ TexRow texrow;
+ texrow.reset();
+ texrow.newline();
+ texrow.newline();
// output paragraphs
if (isDocBook())
- docbookParagraphs(paragraphs(), *this, os, runparams);
+ docbookParagraphs(text(), *this, os, runparams);
else
// latex or literate
- latexParagraphs(*this, text(), os, d->texrow, runparams);
+ latexParagraphs(*this, text(), os, texrow, runparams);
}
}
}
-void Buffer::errors(string const & err) const
+void Buffer::errors(string const & err, bool from_master) const
{
if (gui_)
- gui_->errors(err);
+ gui_->errors(err, from_master);
}
int AutoSaveBuffer::generateChild()
{
+#if defined(__APPLE__)
+ /* FIXME fork() is not usable for autosave on Mac OS X 10.6 (snow leopard)
+ * We should use something else like threads.
+ *
+ * Since I do not know how to determine at run time what is the OS X
+ * version, I just disable forking altogether for now (JMarc)
+ */
+ pid_t const pid = -1;
+#else
// tmp_ret will be located (usually) in /tmp
// will that be a problem?
// Note that this calls ForkedCalls::fork(), so it's
// you should set pid to -1, and comment out the fork.
if (pid != 0 && pid != -1)
return pid;
+#endif
// pid = -1 signifies that lyx was unable
// to fork. But we will do the save
FileName Buffer::getAutosaveFilename() const
{
- string const fpath = isUnnamed() ? lyxrc.document_path : filePath();
+ // 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,
+ // which will most often be the temporary directory
+ string fpath;
+ if (isUnnamed())
+ fpath = lyxrc.backupdir_path.empty() ? lyxrc.document_path
+ : lyxrc.backupdir_path;
+ if (!isUnnamed() || fpath.empty() || !FileName(fpath).exists())
+ fpath = filePath();
+
string const fname = "#" + d->filename.onlyFileName() + "#";
return makeAbsPath(fname, fpath);
}
}
+void Buffer::moveAutosaveFile(support::FileName const & oldauto) const
+{
+ FileName const newauto = getAutosaveFilename();
+ if (!(oldauto == newauto || oldauto.moveTo(newauto)))
+ LYXERR0("Unable to remove autosave file `" << oldauto << "'!");
+}
+
+
// Perfect target for a thread...
void Buffer::autoSave() const
{
string Buffer::bufferFormat() const
{
- if (isDocBook())
- return "docbook";
- if (isLiterate())
- return "literate";
- if (params().useXetex)
- return "xetex";
- if (params().encoding().package() == Encoding::japanese)
- return "platex";
- return "latex";
+ string format = params().documentClass().outputFormat();
+ if (format == "latex") {
+ if (params().useXetex)
+ return "xetex";
+ if (params().encoding().package() == Encoding::japanese)
+ return "platex";
+ }
+ return format;
}
path = p;
}
}
- if (!path.empty())
- runparams.flavor = theConverters().getFlavor(path);
- else {
- Alert::error(_("Couldn't export file"),
- bformat(_("No information for exporting the format %1$s."),
- formats.prettyName(format)));
+ if (path.empty()) {
+ if (!put_in_tempdir) {
+ // Only show this alert if this is an export to a non-temporary
+ // file (not for previewing).
+ Alert::error(_("Couldn't export file"), bformat(
+ _("No information for exporting the format %1$s."),
+ formats.prettyName(format)));
+ }
return false;
}
+ runparams.flavor = theConverters().getFlavor(path);
+
} else {
backend_format = format;
// FIXME: Don't hardcode format names here, but use a flag
updateMacroInstances();
// Plain text backend
- if (backend_format == "text")
+ if (backend_format == "text") {
+ runparams.flavor = OutputParams::TEXT;
writePlaintextFile(*this, FileName(filename), runparams);
- // no backend
- else if (backend_format == "lyx")
+ }
+ // HTML backend
+ else if (backend_format == "xhtml") {
+ runparams.flavor = OutputParams::HTML;
+ makeLyXHTMLFile(FileName(filename), runparams);
+ } else if (backend_format == "lyx")
writeFile(FileName(filename));
// Docbook backend
else if (isDocBook()) {
tmp_result_file, FileName(absFileName()), backend_format, format,
error_list);
// Emit the signal to show the error list.
- if (format != backend_format)
+ if (format != backend_format) {
errors(error_type);
+ // also to the children, in case of master-buffer-view
+ std::vector<Buffer *> clist = getChildren();
+ for (vector<Buffer *>::const_iterator cit = clist.begin();
+ cit != clist.end(); ++cit)
+ (*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
+ // object to the cloned buffer.
+ // 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;
+ }
+
if (put_in_tempdir) {
result_file = tmp_result_file.absFilename();
return true;
}
- result_file = changeExtension(absFileName(), ext);
+ result_file = changeExtension(exportFileName().absFilename(), ext);
// We need to copy referenced files (e. g. included graphics
// if format == "dvi") to the result dir.
vector<ExportedFile> const files =
vector<Format const *> Buffer::exportableFormats(bool only_viewable) const
{
- vector<string> backs = backends();
+ vector<string> const backs = backends();
vector<Format const *> result =
theConverters().getReachable(backs[0], only_viewable, true);
for (vector<string>::const_iterator it = backs.begin() + 1;
vector<string> Buffer::backends() const
{
vector<string> v;
- if (params().baseClass()->isTeXClassAvailable()) {
- v.push_back(bufferFormat());
- // FIXME: Don't hardcode format names here, but use a flag
- if (v.back() == "latex")
- v.push_back("pdflatex");
- }
+ v.push_back(bufferFormat());
+ // FIXME: Don't hardcode format names here, but use a flag
+ if (v.back() == "latex")
+ v.push_back("pdflatex");
+ v.push_back("xhtml");
v.push_back("text");
v.push_back("lyx");
return v;
_("&Recover"), _("&Load Original"),
_("&Cancel")))
{
- case 0:
+ case 0: {
// the file is not saved if we load the emergency file.
markDirty();
- return readFile(e);
+ docstring str;
+ bool res;
+
+ if ((res = readFile(e)) == success)
+ str = _("Document was successfully recovered.");
+ else
+ str = _("Document was NOT successfully recovered.");
+ str += "\n\n" + bformat(_("Remove emergency file now?\n(%1$s)"),
+ from_utf8(e.absFilename()));
+
+ if (!Alert::prompt(_("Delete emergency file?"), str, 1, 1,
+ _("&Remove"), _("&Keep it"))) {
+ e.removeFile();
+ if (res == success)
+ Alert::warning(_("Emergency file deleted"),
+ _("Do not forget to save your file now!"), true);
+ }
+ return res;
+ }
case 1:
+ if (!Alert::prompt(_("Delete emergency file?"),
+ _("Remove emergency file now?"), 1, 1,
+ _("&Remove"), _("&Keep it")))
+ e.removeFile();
break;
default:
return false;
}
-void Buffer::updateLabels(UpdateScope scope) const
+void Buffer::updateLabels(UpdateScope scope, bool out) const
{
// Use the master text class also for child documents
Buffer const * const master = masterBuffer();
// If this is a child document start with the master
if (master != this) {
bufToUpdate.insert(this);
- master->updateLabels();
+ master->updateLabels(UpdateMaster, out);
// Do this here in case the master has no gui associated with it. Then,
// the TocModel is not updated and TocModel::toc_ is invalid (bug 5699).
if (!master->gui_)
- structureChanged();
+ structureChanged();
// was buf referenced from the master (i.e. not in bufToUpdate anymore)?
if (bufToUpdate.find(this) == bufToUpdate.end())
// do the real work
ParIterator parit = cbuf.par_iterator_begin();
- updateLabels(parit);
+ updateLabels(parit, out);
if (master != this)
// TocBackend update will be done later.
// set the label of a paragraph. This includes the counters.
-static void setLabel(Buffer const & buf, ParIterator & it)
+void Buffer::setLabel(ParIterator & it) const
{
- BufferParams const & bp = buf.masterBuffer()->params();
+ BufferParams const & bp = this->masterBuffer()->params();
DocumentClass const & textclass = bp.documentClass();
Paragraph & par = it.paragraph();
Layout const & layout = par.layout();
if (par.params().startOfAppendix()) {
// FIXME: only the counter corresponding to toplevel
- // sectionning should be reset
+ // sectioning should be reset
counters.reset();
counters.appendix(true);
}
// Compute the item depth of the paragraph
par.itemdepth = getItemDepth(it);
- if (layout.margintype == MARGIN_MANUAL) {
+ if (layout.margintype == MARGIN_MANUAL
+ || layout.latextype == LATEX_BIB_ENVIRONMENT) {
if (par.params().labelWidthString().empty())
- par.params().labelWidthString(par.translateIfPossible(layout.labelstring(), bp));
+ par.params().labelWidthString(par.expandLabel(layout, bp));
} else {
par.params().labelWidthString(docstring());
}
case LABEL_COUNTER:
if (layout.toclevel <= bp.secnumdepth
&& (layout.latextype != LATEX_ENVIRONMENT
- || isFirstInSequence(it.pit(), it.plist()))) {
+ || it.text()->isFirstInSequence(it.pit()))) {
counters.step(layout.counter);
par.params().labelString(
par.expandLabel(layout, bp));
}
case LABEL_ENUMERATE: {
- // FIXME: Yes I know this is a really, really! bad solution
- // (Lgb)
- docstring enumcounter = from_ascii("enum");
+ docstring enumcounter = layout.counter.empty() ? from_ascii("enum") : layout.counter;
switch (par.itemdepth) {
case 2:
// Maybe we have to reset the enumeration counter.
if (needEnumCounterReset(it))
counters.reset(enumcounter);
-
counters.step(enumcounter);
- string format;
-
- switch (par.itemdepth) {
- case 0:
- format = N_("\\arabic{enumi}.");
- break;
- case 1:
- format = N_("(\\alph{enumii})");
- break;
- case 2:
- format = N_("\\roman{enumiii}.");
- break;
- case 3:
- format = N_("\\Alph{enumiv}.");
- break;
- default:
- // not a valid enumdepth...
- break;
- }
-
- par.params().labelString(counters.counterLabel(
- par.translateIfPossible(from_ascii(format), bp)));
+ string const & lang = par.getParLanguage(bp)->code();
+ par.params().labelString(counters.theCounter(enumcounter, lang));
break;
}
string const & type = counters.current_float();
docstring full_label;
if (type.empty())
- full_label = buf.B_("Senseless!!! ");
+ full_label = this->B_("Senseless!!! ");
else {
- docstring name = buf.B_(textclass.floats().getType(type).name());
+ docstring name = this->B_(textclass.floats().getType(type).name());
if (counters.hasCounter(from_utf8(type))) {
+ string const & lang = par.getParLanguage(bp)->code();
counters.step(from_utf8(type));
full_label = bformat(from_ascii("%1$s %2$s:"),
name,
- counters.theCounter(from_utf8(type)));
+ counters.theCounter(from_utf8(type), lang));
} else
full_label = bformat(from_ascii("%1$s #:"), name);
}
case LABEL_CENTERED_TOP_ENVIRONMENT:
case LABEL_STATIC:
case LABEL_BIBLIO:
- par.params().labelString(
- par.translateIfPossible(layout.labelstring(), bp));
+ par.params().labelString(par.expandLabel(layout, bp));
break;
}
}
-void Buffer::updateLabels(ParIterator & parit) const
+void Buffer::updateLabels(ParIterator & parit, bool out) const
{
LASSERT(parit.pit() == 0, /**/);
maxdepth = parit->getMaxDepthAfter();
// set the counter for this paragraph
- setLabel(*this, parit);
+ setLabel(parit);
// Now the insets
InsetList::const_iterator iit = parit->insetList().begin();
InsetList::const_iterator end = parit->insetList().end();
for (; iit != end; ++iit) {
parit.pos() = iit->pos;
- iit->inset->updateLabels(parit);
+ iit->inset->updateLabels(parit, out);
}
}
}
-bool Buffer::nextWord(DocIterator & from, DocIterator & to,
- docstring & word) const
-{
- bool inword = false;
- bool ignoreword = false;
- string lang_code;
- // Go backward a bit if needed in order to return the word currently
- // pointed by 'from'.
- while (from && from.pos() && isLetter(from))
- from.backwardPos();
- // OK, we start from here.
- to = from;
- while (to.depth()) {
- if (isLetter(to)) {
- if (!inword) {
- inword = true;
- ignoreword = false;
- from = to;
- word.clear();
- lang_code = to.paragraph().getFontSettings(params(),
- to.pos()).language()->code();
- }
- // Insets like optional hyphens and ligature
- // break are part of a word.
- if (!to.paragraph().isInset(to.pos())) {
- char_type const c = to.paragraph().getChar(to.pos());
- word += c;
- if (isDigit(c))
- ignoreword = true;
- }
- } else { // !isLetter(cur)
- if (inword && !word.empty() && !ignoreword)
- return true;
- inword = false;
- }
- to.forwardPos();
- }
- from = to;
- word.clear();
- return false;
-}
-
-
int Buffer::spellCheck(DocIterator & from, DocIterator & to,
WordLangTuple & word_lang, docstring_list & suggestions) const
{
int progress = 0;
- SpellChecker::Result res = SpellChecker::OK;
- SpellChecker * speller = theSpellChecker();
+ WordLangTuple wl;
suggestions.clear();
- docstring word;
- while (nextWord(from, to, word)) {
- ++progress;
- string lang_code = lyxrc.spellchecker_use_alt_lang
- ? lyxrc.spellchecker_alt_lang
- : from.paragraph().getFontSettings(params(), from.pos()).language()->code();
- WordLangTuple wl(word, lang_code);
- res = speller->check(wl);
- // ... just bail out if the spellchecker reports an error.
- if (!speller->error().empty()) {
- throw ExceptionMessage(WarningException,
- _("The spellchecker has failed."), speller->error());
+ word_lang = WordLangTuple();
+ // OK, we start from here.
+ DocIterator const end = doc_iterator_end(this);
+ for (; from != end; from.forwardPos()) {
+ // We are only interested in text so remove the math CursorSlice.
+ while (from.inMathed()) {
+ from.pop_back();
+ from.pos()++;
}
- if (res != SpellChecker::OK && res != SpellChecker::IGNORED_WORD) {
+ // If from is at the end of the document (which is possible
+ // when leaving the mathed) LyX will crash later.
+ if (from == end)
+ break;
+ to = from;
+ if (from.paragraph().spellCheck(from.pos(), to.pos(), wl, suggestions)) {
word_lang = wl;
break;
}
- from = to;
+
+ // Do not increase progress when from == to, otherwise the word
+ // count will be wrong.
+ if (from != to) {
+ from = to;
+ ++progress;
+ }
}
- while (!(word = speller->nextMiss()).empty())
- suggestions.push_back(word);
return progress;
}
+
+bool Buffer::reload()
+{
+ setBusy(true);
+ // e.g., read-only status could have changed due to version control
+ d->filename.refresh();
+ docstring const disp_fn = makeDisplayPath(d->filename.absFilename());
+
+ bool const success = loadLyXFile(d->filename);
+ if (success) {
+ updateLabels();
+ changed(true);
+ errors("Parse");
+ message(bformat(_("Document %1$s reloaded."), disp_fn));
+ } else {
+ message(bformat(_("Could not reload document %1$s."), disp_fn));
+ }
+ setBusy(false);
+ return success;
+}
+
+
} // namespace lyx