#include "Converter.h"
#include "Counters.h"
#include "Cursor.h"
+#include "CutAndPaste.h"
#include "DispatchResult.h"
#include "DocIterator.h"
#include "Encoding.h"
#include "support/Package.h"
#include "support/PathChanger.h"
#include "support/Systemcall.h"
+#include "support/TempFile.h"
#include "support/textutils.h"
#include "support/types.h"
// if we're the master buffer, then we should get rid of the list
// of clones
if (!parent()) {
- // if this is not empty, we have leaked something. worse, one of the
- // children still has a reference to this list.
- LASSERT(d->clone_list_->empty(), /* */);
+ // If this is not empty, we have leaked something. Worse, one of the
+ // children still has a reference to this list. But we will try to
+ // continue, rather than shut down.
+ LATTEST(d->clone_list_->empty());
list<CloneList *>::iterator it =
find(cloned_buffers.begin(), cloned_buffers.end(), d->clone_list_);
- LASSERT(it != cloned_buffers.end(), /* */);
- cloned_buffers.erase(it);
+ if (it == cloned_buffers.end()) {
+ // We will leak in this case, but it is safe to continue.
+ LATTEST(false);
+ } else
+ cloned_buffers.erase(it);
delete d->clone_list_;
}
// FIXME Do we really need to do this right before we delete d?
return;
Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
+
+ // The clone needs its own DocumentClass, since running updateBuffer() will
+ // modify it, and we would otherwise be sharing it with the original Buffer.
+ buffer_clone->params().makeDocumentClass();
+ ErrorList el;
+ cap::switchBetweenClasses(
+ params().documentClassPtr(), buffer_clone->params().documentClassPtr(),
+ static_cast<InsetText &>(buffer_clone->inset()), el);
+
bufmap[this] = buffer_clone;
clones->insert(buffer_clone);
buffer_clone->d->clone_list_ = clones;
buffer_clone->d->macro_lock = true;
buffer_clone->d->children_positions.clear();
+
// FIXME (Abdel 09/01/2010): this is too complicated. The whole children_positions and
// math macro caches need to be rethought and simplified.
// I am not sure wether we should handle Buffer cloning here or in BufferList.
cloned_buffers.push_back(new CloneList);
CloneList * clones = cloned_buffers.back();
Buffer * buffer_clone = new Buffer(fileName().absFileName(), false, this);
+
+ // The clone needs its own DocumentClass, since running updateBuffer() will
+ // modify it, and we would otherwise be sharing it with the original Buffer.
+ buffer_clone->params().makeDocumentClass();
+ ErrorList el;
+ cap::switchBetweenClasses(
+ params().documentClassPtr(), buffer_clone->params().documentClassPtr(),
+ static_cast<InsetText &>(buffer_clone->inset()), el);
+
clones->insert(buffer_clone);
buffer_clone->d->clone_list_ = clones;
+
// we won't be cloning the children
buffer_clone->d->children_positions.clear();
return buffer_clone;
frontend::WorkAreaManager & Buffer::workAreaManager() const
{
- LASSERT(d->wa_, /**/);
+ LBUFERR(d->wa_);
return *d->wa_;
}
params().html_latex_end.clear();
params().html_math_img_scale = 1.0;
params().output_sync_macro.erase();
- params().local_layout.clear();
+ params().setLocalLayout(string(), false);
+ params().setLocalLayout(string(), true);
for (int i = 0; i < 4; ++i) {
params().user_defined_bullet(i) = ITEMIZE_DEFAULTS[i];
}
+bool Buffer::importString(string const & format, docstring const & contents, ErrorList & errorList)
+{
+ Format const * fmt = formats.getFormat(format);
+ if (!fmt)
+ return false;
+ // It is important to use the correct extension here, since some
+ // converters create a wrong output file otherwise (e.g. html2latex)
+ TempFile const tempfile("Buffer_importStringXXXXXX." + fmt->extension());
+ FileName const name(tempfile.name());
+ ofdocstream os(name.toFilesystemEncoding().c_str());
+ bool const success = (os << contents);
+ os.close();
+
+ bool converted = false;
+ if (success) {
+ params().compressed = false;
+
+ // remove dummy empty par
+ paragraphs().clear();
+
+ converted = importFile(format, name, errorList);
+ }
+
+ if (name.exists())
+ name.removeFile();
+ return converted;
+}
+
+
+bool Buffer::importFile(string const & format, FileName const & name, ErrorList & errorList)
+{
+ if (!theConverters().isReachable(format, "lyx"))
+ return false;
+
+ TempFile const tempfile("Buffer_importFileXXXXXX.lyx");
+ FileName const lyx(tempfile.name());
+ if (theConverters().convert(0, name, lyx, name, format, "lyx", errorList))
+ return readFile(lyx) == ReadSuccess;
+
+ return false;
+}
+
+
bool Buffer::readString(string const & s)
{
params().compressed = false;
FileName const fn = FileName::tempName("Buffer_readString");
int file_format;
- ReadStatus const ret_plf = parseLyXFormat(lex, fn, file_format);
- if (ret_plf != ReadSuccess)
- return ret_plf;
+ bool success = parseLyXFormat(lex, fn, file_format) == ReadSuccess;
- if (file_format != LYX_FORMAT) {
+ if (success && file_format != LYX_FORMAT) {
// We need to call lyx2lyx, so write the input to a file
ofstream os(fn.toFilesystemEncoding().c_str());
os << s;
os.close();
// lyxvc in readFile
- return readFile(fn) == ReadSuccess;
+ if (readFile(fn) != ReadSuccess)
+ success = false;
}
-
- if (readDocument(lex))
- return false;
- return true;
+ else if (success)
+ if (readDocument(lex))
+ success = false;
+ if (fn.exists())
+ fn.removeFile();
+ return success;
}
Buffer::ReadStatus Buffer::convertLyXFormat(FileName const & fn,
FileName & tmpfile, int from_format)
{
- tmpfile = FileName::tempName("Buffer_convertLyXFormat");
+ tmpfile = FileName::tempName("Buffer_convertLyXFormatXXXXXX.lyx");
if(tmpfile.empty()) {
Alert::error(_("Conversion failed"),
bformat(_("%1$s is from a different"
bool Buffer::writeFile(FileName const & fname) const
{
- // FIXME Do we need to do these here? I don't think writing
- // the LyX file depends upon it. (RGH)
- // updateBuffer();
- // updateMacroInstances();
-
if (d->read_only && fname == d->filename)
return false;
if (output_body_tag)
os << "<body>\n";
XHTMLStream xs(os);
- params().documentClass().counters().reset();
+ if (output != IncludedFile)
+ // if we're an included file, the counters are in the master.
+ params().documentClass().counters().reset();
xhtmlParagraphs(text(), *this, xs, runparams);
if (output_body_tag)
os << "</body>\n";
if (res == -1) {
Alert::error(_("chktex failure"),
_("Could not run chktex successfully."));
- } else if (res > 0) {
+ } else {
ErrorList & errlist = d->errorLists["ChkTeX"];
errlist.clear();
bufferErrors(terr, errlist);
}
+void Buffer::makeCitationLabels() const
+{
+ Buffer const * const master = masterBuffer();
+ return d->bibinfo_.makeCitationLabels(*master);
+}
+
+
bool Buffer::citeLabelsValid() const
{
return masterBuffer()->d->cite_labels_valid_;
switch (cmd.action()) {
- case LFUN_BUFFER_TOGGLE_READ_ONLY:
- flag.setOnOff(isReadonly());
- break;
+ case LFUN_BUFFER_TOGGLE_READ_ONLY:
+ flag.setOnOff(isReadonly());
+ break;
// FIXME: There is need for a command-line import.
//case LFUN_BUFFER_IMPORT:
- case LFUN_BUFFER_AUTO_SAVE:
- break;
+ case LFUN_BUFFER_AUTO_SAVE:
+ break;
- case LFUN_BUFFER_EXPORT_CUSTOM:
- // FIXME: Nothing to check here?
- break;
+ case LFUN_BUFFER_EXPORT_CUSTOM:
+ // FIXME: Nothing to check here?
+ break;
- case LFUN_BUFFER_EXPORT: {
- docstring const arg = cmd.argument();
- if (arg == "custom") {
- enable = true;
- break;
- }
- string format = to_utf8(arg);
- size_t pos = format.find(' ');
- if (pos != string::npos)
- format = format.substr(0, pos);
- enable = params().isExportable(format);
- if (!enable)
- flag.message(bformat(
- _("Don't know how to export to format: %1$s"), arg));
+ case LFUN_BUFFER_EXPORT: {
+ docstring const arg = cmd.argument();
+ if (arg == "custom") {
+ enable = true;
break;
}
+ string format = to_utf8(arg);
+ size_t pos = format.find(' ');
+ if (pos != string::npos)
+ format = format.substr(0, pos);
+ enable = params().isExportable(format);
+ if (!enable)
+ flag.message(bformat(
+ _("Don't know how to export to format: %1$s"), arg));
+ break;
+ }
- case LFUN_BUFFER_CHKTEX:
- enable = params().isLatex() && !lyxrc.chktex_command.empty();
- break;
+ case LFUN_BUFFER_CHKTEX:
+ enable = params().isLatex() && !lyxrc.chktex_command.empty();
+ break;
- case LFUN_BUILD_PROGRAM:
- enable = params().isExportable("program");
- break;
+ case LFUN_BUILD_PROGRAM:
+ enable = params().isExportable("program");
+ break;
- case LFUN_BRANCH_ADD:
- case LFUN_BRANCHES_RENAME:
- case LFUN_BUFFER_PRINT:
- // if no Buffer is present, then of course we won't be called!
- break;
+ case LFUN_BRANCH_ACTIVATE:
+ case LFUN_BRANCH_DEACTIVATE:
+ case LFUN_BRANCH_MASTER_ACTIVATE:
+ case LFUN_BRANCH_MASTER_DEACTIVATE: {
+ bool const master = (cmd.action() == LFUN_BRANCH_MASTER_ACTIVATE
+ || cmd.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
+ BranchList const & branchList = master ? masterBuffer()->params().branchlist()
+ : params().branchlist();
+ docstring const branchName = cmd.argument();
+ flag.setEnabled(!branchName.empty() && branchList.find(branchName));
+ break;
+ }
- case LFUN_BUFFER_LANGUAGE:
- enable = !isReadonly();
- break;
+ case LFUN_BRANCH_ADD:
+ case LFUN_BRANCHES_RENAME:
+ case LFUN_BUFFER_PRINT:
+ // if no Buffer is present, then of course we won't be called!
+ break;
- default:
- return false;
+ case LFUN_BUFFER_LANGUAGE:
+ enable = !isReadonly();
+ break;
+
+ default:
+ return false;
}
flag.setEnabled(enable);
return true;
resetAutosaveTimers();
break;
+ case LFUN_BRANCH_ACTIVATE:
+ case LFUN_BRANCH_DEACTIVATE:
+ case LFUN_BRANCH_MASTER_ACTIVATE:
+ case LFUN_BRANCH_MASTER_DEACTIVATE: {
+ bool const master = (func.action() == LFUN_BRANCH_MASTER_ACTIVATE
+ || func.action() == LFUN_BRANCH_MASTER_DEACTIVATE);
+ Buffer * buf = master ? const_cast<Buffer *>(masterBuffer())
+ : this;
+
+ docstring const branch_name = func.argument();
+ // the case without a branch name is handled elsewhere
+ if (branch_name.empty()) {
+ dispatched = false;
+ break;
+ }
+ Branch * branch = buf->params().branchlist().find(branch_name);
+ if (!branch) {
+ LYXERR0("Branch " << branch_name << " does not exist.");
+ dr.setError(true);
+ docstring const msg =
+ bformat(_("Branch \"%1$s\" does not exist."), branch_name);
+ dr.setMessage(msg);
+ break;
+ }
+ bool const activate = (func.action() == LFUN_BRANCH_ACTIVATE
+ || func.action() == LFUN_BRANCH_MASTER_ACTIVATE);
+ if (branch->isSelected() != activate) {
+ buf->undo().recordUndoFullDocument(CursorData());
+ branch->setSelected(activate);
+ dr.setError(false);
+ dr.screenUpdate(Update::Force);
+ dr.forceBufferUpdate();
+ }
+ break;
+ }
+
case LFUN_BRANCH_ADD: {
docstring branch_name = func.argument();
if (branch_name.empty()) {
void Buffer::changeLanguage(Language const * from, Language const * to)
{
- LASSERT(from, /**/);
- LASSERT(to, /**/);
+ LASSERT(from, return);
+ LASSERT(to, return);
for_each(par_iterator_begin(),
par_iterator_end(),
bool Buffer::isExternallyModified(CheckMethod method) const
{
- LASSERT(d->filename.exists(), /**/);
+ LASSERT(d->filename.exists(), return false);
// if method == timestamp, check timestamp before checksum
return (method == checksum_method
|| d->timestamp_ != d->filename.lastModified())
string Buffer::filePath() const
{
- int last = d->filename.onlyPath().absFileName().length() - 1;
+ string const abs = d->filename.onlyPath().absFileName();
+ if (abs.empty())
+ return abs;
+ int last = abs.length() - 1;
- return d->filename.onlyPath().absFileName()[last] == '/'
- ? d->filename.onlyPath().absFileName()
- : d->filename.onlyPath().absFileName() + "/";
+ return abs[last] == '/' ? abs : abs + '/';
}
}
-Buffer::References & Buffer::references(docstring const & label)
+Buffer::References & Buffer::getReferenceCache(docstring const & label)
{
if (d->parent())
- return const_cast<Buffer *>(masterBuffer())->references(label);
+ return const_cast<Buffer *>(masterBuffer())->getReferenceCache(label);
RefCache::iterator it = d->ref_cache_.find(label);
if (it != d->ref_cache_.end())
Buffer::References const & Buffer::references(docstring const & label) const
{
- return const_cast<Buffer *>(this)->references(label);
+ return const_cast<Buffer *>(this)->getReferenceCache(label);
+}
+
+
+void Buffer::addReference(docstring const & label, Inset * inset, ParIterator it)
+{
+ References & refs = getReferenceCache(label);
+ refs.push_back(make_pair(inset, it));
}
}
-void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
- InsetCode code)
+void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to)
{
//FIXME: This does not work for child documents yet.
- LASSERT(code == CITE_CODE, /**/);
-
reloadBibInfoCache();
// Check if the label 'from' appears more than once
string const paramName = "key";
for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
- if (it->lyxCode() == code) {
- InsetCommand * inset = it->asInsetCommand();
- if (!inset)
- continue;
- docstring const oldValue = inset->getParam(paramName);
- if (oldValue == from)
- inset->setParam(paramName, to);
- }
+ if (it->lyxCode() != CITE_CODE)
+ continue;
+ InsetCommand * inset = it->asInsetCommand();
+ docstring const oldValue = inset->getParam(paramName);
+ if (oldValue == from)
+ inset->setParam(paramName, to);
}
}
}
-// helper class, to guarantee this gets reset properly
-class Buffer::MarkAsExporting {
-public:
- MarkAsExporting(Buffer const * buf) : buf_(buf)
- {
- LASSERT(buf_, /* */);
- buf_->setExportStatus(true);
- }
- ~MarkAsExporting()
- {
- buf_->setExportStatus(false);
- }
-private:
- Buffer const * const buf_;
-};
-
-
-
void Buffer::setExportStatus(bool e) const
{
d->doing_export = e;
void Buffer::updateBuffer(UpdateScope scope, UpdateType utype) const
{
+ LBUFERR(!text().paragraphs().empty());
+
// Use the master text class also for child documents
Buffer const * const master = masterBuffer();
DocumentClass const & textclass = master->params().documentClass();
// do this only if we are the top-level Buffer
- if (master == this)
+ if (master == this) {
+ textclass.counters().reset(from_ascii("bibitem"));
reloadBibInfoCache();
+ }
// keep the buffers to be children in this set. If the call from the
// master comes back we can see which of them were actually seen (i.e.
Buffer & cbuf = const_cast<Buffer &>(*this);
- LASSERT(!text().paragraphs().empty(), /**/);
-
// do the real work
ParIterator parit = cbuf.par_iterator_begin();
updateBuffer(parit, utype);
d->bibinfo_cache_valid_ = true;
d->cite_labels_valid_ = true;
- cbuf.tocBackend().update();
+ cbuf.tocBackend().update(utype == OutputUpdate);
if (scope == UpdateMaster)
cbuf.structureChanged();
}
static bool needEnumCounterReset(ParIterator const & it)
{
Paragraph const & par = *it;
- LASSERT(par.layout().labeltype == LABEL_ENUMERATE, /**/);
+ LASSERT(par.layout().labeltype == LABEL_ENUMERATE, return false);
depth_type const cur_depth = par.getDepth();
ParIterator prev_it = it;
while (prev_it.pit()) {
}
switch(layout.labeltype) {
- case LABEL_COUNTER:
- if (layout.toclevel <= bp.secnumdepth
- && (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;
-
case LABEL_ITEMIZE: {
// At some point of time we should do something more
// clever here, like:
par.params().labelString(docstring());
break;
+ case LABEL_ABOVE:
+ case LABEL_CENTERED:
+ case LABEL_STATIC: {
+ docstring const & lcounter = layout.counter;
+ if (!lcounter.empty()) {
+ if (layout.toclevel <= bp.secnumdepth
+ && (layout.latextype != LATEX_ENVIRONMENT
+ || it.text()->isFirstInSequence(it.pit()))) {
+ if (counters.hasCounter(lcounter))
+ counters.step(lcounter, utype);
+ par.params().labelString(par.expandLabel(layout, bp));
+ } else
+ par.params().labelString(docstring());
+ } else
+ par.params().labelString(par.expandLabel(layout, bp));
+ break;
+ }
+
case LABEL_MANUAL:
- case LABEL_TOP_ENVIRONMENT:
- case LABEL_CENTERED_TOP_ENVIRONMENT:
- case LABEL_STATIC:
case LABEL_BIBLIO:
par.params().labelString(par.expandLabel(layout, bp));
- break;
}
}
void Buffer::updateBuffer(ParIterator & parit, UpdateType utype) const
{
+ // LASSERT: Is it safe to continue here, or should we just return?
LASSERT(parit.pit() == 0, /**/);
// Set the position of the text in the buffer to be able