-/* This file is part of
- * ======================================================
+/**
+ * \file buffer.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
*
- * LyX, The Document Processor
+ * \author Lars Gullik Bjønnes
*
- * Copyright 1995 Matthias Ettrich
- * Copyright 1995-2001 The LyX Team.
- *
- * This file is Copyright 1996-2001
- * Lars Gullik Bjønnes
- *
- * ======================================================
+ * Full author contact details are available in file CREDITS
*/
#include <config.h>
#include "lyxtextclasslist.h"
#include "sgml.h"
#include "paragraph_funcs.h"
+#include "messages.h"
#include "author.h"
#include "frontends/LyXView.h"
#include <boost/bind.hpp>
#include <boost/tuple/tuple.hpp>
-#include "BoostFormat.h"
+#include "support/BoostFormat.h"
#include <fstream>
#include <iomanip>
if (users)
users->buffer(0);
- if (!tmppath.empty()) {
- DestroyBufferTmpDir(tmppath);
+ if (!tmppath.empty() && destroyDir(tmppath) != 0) {
+#if USE_BOOST_FORMAT
+ boost::format fmt = _("Could not remove the temporary directory %1$s");
+ fmt % tmppath;
+ string msg = fmt.str();
+#else
+ string msg = _("Could not remove the temporary directory ") + tmppath;
+#endif
+ Alert::warning(_("Could not remove temporary directory"), msg);
}
paragraphs.clear();
// We'll remove this later. (Lgb)
namespace {
-#ifdef WITH_WARNINGS
-#warning this is never set to != 0 !!! - remove ?
-#endif
-int unknown_layouts;
-
void unknownClass(string const & unknown)
{
string msg =
#if USE_BOOST_FORMAT
boost::io::str(boost::format(
- _("The document uses an unknown textclass \"%1$s\".")) % unknown)
- + _("-- substituting default.");
+ _("Using the default document class, because the "
+ " class %1$s is unknown.")) % unknown);
#else
- _("The document uses an unknown textclass ")
- + unknown + _("-- substituting default.");
+ _("Using the default document class, because the "
+ " class ") + unknown + (" is unknown.");
#endif
- Alert::alert(_("Textclass error"), msg);
+ Alert::warning(_("Unknown document class"), msg);
}
} // anon
if (unknown[0] != '\\') {
unknownClass(unknown);
} else {
- ++unknown_tokens;
+ ++unknown_tokens;
}
}
}
// Returns false if "\the_end" is not read (Asger)
bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit)
{
- unknown_layouts = 0;
int unknown_tokens = 0;
Paragraph::depth_type depth = 0;
unknown_tokens += readHeader(lex);
if (!params.getLyXTextClass().load()) {
+ string theclass = params.getLyXTextClass().name();
+ string msg =
#if USE_BOOST_FORMAT
- Alert::alert(_("Textclass Loading Error!"),
- boost::io::str(boost::format(_("Can't load textclass %1$s")) %
- params.getLyXTextClass().name()),
- _("-- substituting default."));
+ boost::io::str(boost::format(
+ _("Using the default document class, because the "
+ " class %1$s could not be loaded.")) % theclass);
#else
- Alert::alert(_("Textclass Loading Error!"),
- _("Can't load textclass ")
- + params.getLyXTextClass().name(),
- _("-- substituting default."));
+ _("Using the default document class, because the "
+ " class ") + theclass + (" could not be loaded.");
#endif
+ Alert::error(_("Can't load document class"), msg);
params.textclass = 0;
}
} else {
// We are inserting into an existing document
users->text->breakParagraph(paragraphs);
- markDirty();
// We don't want to adopt the parameters from the
// document we insert, so read them into a temporary buffer
unknown_tokens += readParagraph(lex, token, paragraphs, pit, depth);
}
- if (unknown_layouts > 0) {
- string s = _("Couldn't set the layout for ");
- if (unknown_layouts == 1) {
- s += _("one paragraph");
+
+ if (unknown_tokens > 0) {
+#if USE_BOOST_FORMAT
+ string s;
+ if (unknown_tokens == 1) {
+ boost::format fmt(_("Encountered one unknown token when reading the document %1$s."));
+ fmt % fileName();
+ s = fmt.str();
} else {
- s += tostr(unknown_layouts);
- s += _(" paragraphs");
+ boost::format fmt(_("Encountered %1$s unknown tokens when reading the document %2$s."));
+ fmt % tostr(unknown_tokens);
+ fmt % fileName();
+ s = fmt.str();
}
-#if USE_BOOST_FORMAT
- Alert::alert(_("Textclass Loading Error!"), s,
- boost::io::str(boost::format(_("When reading %1$s")) % fileName()));
#else
- Alert::alert(_("Textclass Loading Error!"), s,
- _("When reading ") + fileName());
-#endif
- }
-
- if (unknown_tokens > 0) {
string s = _("Encountered ");
if (unknown_tokens == 1) {
s += _("one unknown token");
s += tostr(unknown_tokens);
s += _(" unknown tokens");
}
-#if USE_BOOST_FORMAT
- Alert::alert(_("Textclass Loading Error!"), s,
- boost::io::str(boost::format(_("When reading %1$s")) % fileName()));
-#else
- Alert::alert(_("Textclass Loading Error!"), s,
- _("When reading ") + fileName());
+ Alert::warning(_("Document format failure"), s);
#endif
}
// needed to insert the selection
-void Buffer::insertStringAsLines(Paragraph *& par, pos_type & pos,
+void Buffer::insertStringAsLines(ParagraphList::iterator & par, pos_type & pos,
LyXFont const & fn,string const & str)
{
LyXLayout_ptr const & layout = par->layout();
if (autobreakrows && (!par->empty() || layout->keepempty)) {
breakParagraph(params, paragraphs, par, pos,
layout->isEnvironment());
- par = par->next();
+ ++par;
pos = 0;
space_inserted = true;
} else {
bool Buffer::readFile(LyXLex & lex, string const & filename)
{
- return readFile(lex, filename, paragraphs.begin());
-}
-
-
-bool Buffer::readFile(LyXLex & lex, string const & filename, ParagraphList::iterator pit)
-{
- if (lex.isOK()) {
- lex.next();
- string const token(lex.getString());
- if (token == "\\lyxformat") { // the first token _must_ be...
- lex.eatLine();
- string tmp_format = lex.getString();
- //lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
- // if present remove ".," from string.
- string::size_type dot = tmp_format.find_first_of(".,");
- //lyxerr << " dot found at " << dot << endl;
- if (dot != string::npos)
- tmp_format.erase(dot, 1);
- file_format = strToInt(tmp_format);
- //lyxerr << "format: " << file_format << endl;
- if (file_format == LYX_FORMAT) {
- // current format
- } else if (file_format > LYX_FORMAT) {
- // future format
- Alert::alert(_("Warning!"),
- _("The file was created with a newer version of "
- "LyX. This is likely to cause problems."));
-
- } else if (file_format < LYX_FORMAT) {
- // old formats
- if (file_format < 200) {
- Alert::alert(_("ERROR!"),
- _("Old LyX file format found. "
- "Use LyX 0.10.x to read this!"));
- return false;
- } else if (!filename.empty()) {
- string command =
- LibFileSearch("lyx2lyx", "lyx2lyx");
- if (command.empty()) {
- Alert::alert(_("ERROR!"),
- _("Can't find conversion script."));
- return false;
- }
- command += " -t"
- +tostr(LYX_FORMAT) + ' '
- + QuoteName(filename);
- lyxerr[Debug::INFO] << "Running '"
- << command << '\''
- << endl;
- cmd_ret const ret = RunCommand(command);
- if (ret.first) {
- Alert::alert(_("ERROR!"),
- _("An error occured while "
- "running the conversion script."));
- return false;
- }
- istringstream is(STRCONV(ret.second));
- LyXLex tmplex(0, 0);
- tmplex.setStream(is);
- return readFile(tmplex, string(), pit);
- } else {
- // This code is reached if lyx2lyx failed (for
- // some reason) to change the file format of
- // the file.
- lyx::Assert(false);
- return false;
- }
- }
- bool the_end = readBody(lex, pit);
- params.setPaperStuff();
+ bool ret = readFile(lex, filename, paragraphs.begin());
+
+ // After we have read a file, we must ensure that the buffer
+ // language is set and used in the gui.
+ // If you know of a better place to put this, please tell me. (Lgb)
+ updateDocLang(params.language);
- if (!the_end) {
- Alert::alert(_("Warning!"),
- _("Reading of document is not complete"),
- _("Maybe the document is truncated"));
+ return ret;
+}
+
+
+// FIXME: all the below Alerts should give the filename..
+bool Buffer::readFile(LyXLex & lex, string const & filename,
+ ParagraphList::iterator pit)
+{
+ if (!lex.isOK()) {
+ Alert::error(_("Document could not be read"),
+ _("The specified document could not be read."));
+ return false;
+ }
+
+ lex.next();
+ string const token(lex.getString());
+
+ if (!lex.isOK()) {
+ Alert::error(_("Document could not be read"),
+ _("The specified document could not be read."));
+ return false;
+ }
+
+ // the first token _must_ be...
+ if (token != "\\lyxformat") {
+ Alert::error(_("Document format failure"),
+ _("The specified document is not a LyX document."));
+ return false;
+ }
+
+ lex.eatLine();
+ string tmp_format = lex.getString();
+ //lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
+ // if present remove ".," from string.
+ string::size_type dot = tmp_format.find_first_of(".,");
+ //lyxerr << " dot found at " << dot << endl;
+ if (dot != string::npos)
+ tmp_format.erase(dot, 1);
+ file_format = strToInt(tmp_format);
+ //lyxerr << "format: " << file_format << endl;
+ if (file_format == LYX_FORMAT) {
+ // current format
+ } else if (file_format > LYX_FORMAT) {
+ Alert::warning(_("Document format failure"),
+ _("This document was created with a newer version of "
+ "LyX. This is likely to cause problems."));
+ } else if (file_format < LYX_FORMAT) {
+ // old formats
+ if (file_format < 200) {
+ Alert::error(_("Document format failure"),
+ _("This LyX document is too old to be read "
+ "by this version of LyX. Try LyX 0.10."));
+ return false;
+ } else if (!filename.empty()) {
+ string command =
+ LibFileSearch("lyx2lyx", "lyx2lyx");
+ if (command.empty()) {
+ Alert::error(_("Conversion script not found"),
+ _("The document is from an earlier version "
+ "of LyX, but the conversion script lyx2lyx "
+ "could not be found."));
+ return false;
}
- return true;
- } else { // "\\lyxformat" not found
- Alert::alert(_("ERROR!"), _("Not a LyX file!"));
+ command += " -t"
+ +tostr(LYX_FORMAT) + ' '
+ + QuoteName(filename);
+ lyxerr[Debug::INFO] << "Running '"
+ << command << '\''
+ << endl;
+ cmd_ret const ret = RunCommand(command);
+ if (ret.first) {
+ Alert::error(_("Conversion script failed"),
+ _("The document is from an earlier version "
+ "of LyX, but the lyx2lyx script failed "
+ "to convert it."));
+ return false;
+ }
+ istringstream is(STRCONV(ret.second));
+ LyXLex tmplex(0, 0);
+ tmplex.setStream(is);
+ return readFile(tmplex, string(), pit);
+ } else {
+ // This code is reached if lyx2lyx failed (for
+ // some reason) to change the file format of
+ // the file.
+ lyx::Assert(false);
+ return false;
}
- } else
- Alert::alert(_("ERROR!"), _("Unable to read file!"));
- return false;
+ }
+ bool the_end = readBody(lex, pit);
+ params.setPaperStuff();
+
+ if (!the_end) {
+ Alert::error(_("Document format failure"),
+ _("The document ended unexpectedly, which means "
+ "that it is probably corrupted."));
+ }
+ return true;
}
/* noindent ? */
/* what about the alignment */
-// } else {
-// lyxerr << "Should this ever happen?" << endl;
-// }
// linelen <= 0 is special and means we don't have paragraph breaks
{
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::err_alert(_("Error: Cannot write file:"), fname);
+ string const file = MakeDisplayPath(fname, 50);
+#if USE_BOOST_FORMAT
+ boost::format fmt(_("Could not save the document\n%1$s."));
+ fmt % file;
+ string text = fmt.str();
+#else
+ string text = _("Could not save the document\n");
+ text += file + ".";
+#endif
+ Alert::error(_("Could not save document"), text);
return;
}
writeFileAscii(ofs, linelen);
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::err_alert(_("Error: Cannot open file: "), fname);
+ string const file = MakeDisplayPath(fname, 50);
+#if USE_BOOST_FORMAT
+ boost::format fmt(_("Could not open the specified document\n%1$s."));
+ fmt % file;
+ string text = fmt.str();
+#else
+ string text = _("Could not open the specified document\n");
+ text += file + ".";
+#endif
+ Alert::error(_("Could not open file"), text);
return;
}
texrow.reset();
// The starting paragraph of the coming rows is the
// first paragraph of the document. (Asger)
- texrow.start(&*(paragraphs.begin()), 0);
+ texrow.start(paragraphs.begin()->id(), 0);
if (!only_body && nice) {
os << "%% " << lyx_docversion << " created this file. "
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::alert(_("LYX_ERROR:"), _("Cannot write file"), fname);
+ string const file = MakeDisplayPath(fname, 50);
+#if USE_BOOST_FORMAT
+ boost::format fmt(_("Could not save the specified document\n%1$s.\n"));
+ fmt % file;
+ string text = fmt.str();
+#else
+ string text = _("Could not save the specified document\n");
+ text += file + _(".\n");
+#endif
+ Alert::error(_("Could not save document"), text);
return;
}
<< " -->\n";
Paragraph::depth_type depth = 0; // paragraph depth
- Paragraph * par = &*(paragraphs.begin());
string item_name;
vector<string> environment_stack(5);
- while (par) {
- LyXLayout_ptr const & style = par->layout();
+ ParagraphList::iterator pit = paragraphs.begin();
+ ParagraphList::iterator pend = paragraphs.end();
+ for (; pit != pend; ++pit) {
+ LyXLayout_ptr const & style = pit->layout();
// treat <toc> as a special case for compatibility with old code
- if (par->isInset(0)) {
- Inset * inset = par->getInset(0);
+ if (pit->isInset(0)) {
+ Inset * inset = pit->getInset(0);
Inset::Code lyx_code = inset->lyxCode();
if (lyx_code == Inset::TOC_CODE) {
string const temp = "toc";
sgml::openTag(ofs, depth, false, temp);
-
- par = par->next();
continue;
}
}
// environment tag closing
- for (; depth > par->params().depth(); --depth) {
+ for (; depth > pit->params().depth(); --depth) {
sgml::closeTag(ofs, depth, false, environment_stack[depth]);
environment_stack[depth].erase();
}
// write opening SGML tags
switch (style->latextype) {
case LATEX_PARAGRAPH:
- if (depth == par->params().depth()
+ if (depth == pit->params().depth()
&& !environment_stack[depth].empty()) {
sgml::closeTag(ofs, depth, false, environment_stack[depth]);
environment_stack[depth].erase();
break;
case LATEX_COMMAND:
- if (depth!= 0)
- sgmlError(par, 0,
+ if (depth != 0)
+ sgmlError(&*pit, 0,
_("Error: Wrong depth for LatexType Command.\n"));
if (!environment_stack[depth].empty()) {
{
string const & latexname = style->latexname();
- if (depth == par->params().depth()
+ if (depth == pit->params().depth()
&& environment_stack[depth] != latexname) {
sgml::closeTag(ofs, depth, false,
environment_stack[depth]);
environment_stack[depth].erase();
}
- if (depth < par->params().depth()) {
- depth = par->params().depth();
+ if (depth < pit->params().depth()) {
+ depth = pit->params().depth();
environment_stack[depth].erase();
}
if (environment_stack[depth] != latexname) {
break;
}
- simpleLinuxDocOnePar(ofs, par, depth);
-
- par = par->next();
+ simpleLinuxDocOnePar(ofs, pit, depth);
ofs << "\n";
// write closing SGML tags
// Handle internal paragraph parsing -- layout already processed.
void Buffer::simpleLinuxDocOnePar(ostream & os,
- Paragraph * par,
- Paragraph::depth_type /*depth*/)
+ ParagraphList::iterator par,
+ Paragraph::depth_type /*depth*/) const
{
LyXLayout_ptr const & style = par->layout();
PAR_TAG tag_close = NONE;
list < PAR_TAG > tag_open;
- LyXFont const font = par->getFont(params, i);
+ LyXFont const font = par->getFont(params, i, outerFont(par, paragraphs));
if (font_old.family() != font.family()) {
switch (family_type) {
// Print an error message.
-void Buffer::sgmlError(Paragraph * /*par*/, int /*pos*/,
+void Buffer::sgmlError(ParagraphList::iterator /*par*/, int /*pos*/,
string const & /*message*/) const
{
#ifdef WITH_WARNINGS
{
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::alert(_("LYX_ERROR:"), _("Cannot write file"), fname);
+ string const file = MakeDisplayPath(fname, 50);
+#if USE_BOOST_FORMAT
+ boost::format fmt(_("Could not save the specified document\n%1$s.\n"));
+ fmt % file;
+ string text = fmt.str();
+#else
+ string text = _("Could not save the specified document\n");
+ text += file + _(".\n");
+#endif
+ Alert::error(_("Could not save document"), text);
return;
}
- Paragraph * par = &*(paragraphs.begin());
-
niceFile = nice; // this will be used by Insetincludes.
LaTeXFeatures features(params);
string item_name;
string command_name;
- while (par) {
+ ParagraphList::iterator par = paragraphs.begin();
+ ParagraphList::iterator pend = paragraphs.end();
+
+ for (; par != pend; ++par) {
string sgmlparam;
string c_depth;
string c_params;
simpleDocBookOnePar(ofs, par, desc_on,
depth + 1 + command_depth);
- par = par->next();
string end_tag;
// write closing SGML tags
void Buffer::simpleDocBookOnePar(ostream & os,
- Paragraph * par, int & desc_on,
+ ParagraphList::iterator par, int & desc_on,
Paragraph::depth_type depth) const
{
bool emph_flag = false;
// parsing main loop
for (pos_type i = 0; i < par->size(); ++i) {
- LyXFont font = par->getFont(params, i);
+ LyXFont font = par->getFont(params, i, outerFont(par, paragraphs));
// handle <emphasis> tag
if (font_old.emph() != font.emph()) {
int res = chktex.run(terr); // run chktex
if (res == -1) {
- Alert::alert(_("chktex did not work!"),
- _("Could not run with file:"), name);
+ Alert::error(_("chktex failure"),
+ _("Could not run chktex successfully."));
} else if (res > 0) {
// Insert all errors as errors boxes
users->insertErrors(terr);
void Buffer::changeLanguage(Language const * from, Language const * to)
{
+ lyxerr << "Changing Language!" << endl;
+
+ // Take care of l10n/i18n
+ updateDocLang(to);
ParIterator end = par_iterator_end();
for (ParIterator it = par_iterator_begin(); it != end; ++it)
}
+void Buffer::updateDocLang(Language const * nlang)
+{
+ messages_.reset(new Messages(nlang->code()));
+}
+
+
bool Buffer::isMultiLingual()
{
ParIterator end = par_iterator_end();
}
-Paragraph * Buffer::getParFromID(int id) const
+ParagraphList::iterator Buffer::getParFromID(int id) const
{
- if (id < 0)
- return 0;
-
- // why should we allow < 0 ??
- //lyx::Assert(id >= 0);
+#warning FIXME: const correctness! (Andre)
+ ParIterator it(const_cast<Buffer*>(this)->par_iterator_begin());
+ ParIterator end(const_cast<Buffer*>(this)->par_iterator_end());
- ParConstIterator it(par_iterator_begin());
- ParConstIterator end(par_iterator_end());
+#warning FIXME, perhaps this func should return a ParIterator? (Lgb)
+ if (id < 0) {
+ // John says this is called with id == -1 from undo
+ lyxerr << "getParFromID(), id: " << id << endl;
+ return 0;
+ }
for (; it != end; ++it) {
// go on then, show me how to remove
// the cast
if ((*it)->id() == id) {
- return const_cast<Paragraph*>(*it);
+ return *it;
}
}
}
+bool Buffer::hasParWithID(int id) const
+{
+ ParIterator it(const_cast<Buffer*>(this)->par_iterator_begin());
+ ParIterator end(const_cast<Buffer*>(this)->par_iterator_end());
+
+ if (id < 0) {
+ // John says this is called with id == -1 from undo
+ lyxerr << "hasParWithID(), id: " << id << endl;
+ return 0;
+ }
+
+ for (; it != end; ++it)
+ if ((*it)->id() == id)
+ return true;
+
+ return false;
+}
+
+
ParIterator Buffer::par_iterator_begin()
{
return ParIterator(&*(paragraphs.begin()));
}
+string const Buffer::B_(string const & l10n) const
+{
+ if (messages_.get()) {
+ return messages_->get(l10n);
+ }
+
+ return _(l10n);
+}
+
+
bool Buffer::isClean() const
{
return lyx_clean;
}
-Paragraph * Buffer::inset_iterator::getPar()
+ParagraphList::iterator Buffer::inset_iterator::getPar() const
{
- return &(*pit);
+ return pit;
}