-/* 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 "gettext.h"
#include "language.h"
#include "exporter.h"
+#include "errorlist.h"
#include "Lsstream.h"
#include "format.h"
#include "BufferView.h"
#include "lyxtextclasslist.h"
#include "sgml.h"
#include "paragraph_funcs.h"
+#include "messages.h"
#include "author.h"
#include "frontends/LyXView.h"
#include "mathed/formulamacro.h"
#include "mathed/formula.h"
-#include "insets/inset.h"
#include "insets/inseterror.h"
-#include "insets/insethfill.h"
-#include "insets/insetlabel.h"
-#include "insets/insetref.h"
-#include "insets/inseturl.h"
-#include "insets/insetnote.h"
-#include "insets/insetquotes.h"
-#include "insets/insetlatexaccent.h"
#include "insets/insetbibitem.h"
#include "insets/insetbibtex.h"
-#include "insets/insetcite.h"
-#include "insets/insetexternal.h"
-#include "insets/insetindex.h"
#include "insets/insetinclude.h"
-#include "insets/insettoc.h"
-#include "insets/insetparent.h"
-#include "insets/insetspecialchar.h"
#include "insets/insettext.h"
-#include "insets/insetert.h"
-#include "insets/insetgraphics.h"
-#include "insets/insetfoot.h"
-#include "insets/insetmarginal.h"
-#include "insets/insetoptarg.h"
-#include "insets/insetminipage.h"
-#include "insets/insetfloat.h"
-#include "insets/insetwrap.h"
-#include "insets/insettabular.h"
-#if 0
-#include "insets/insettheorem.h"
-#include "insets/insetlist.h"
-#endif
-#include "insets/insetcaption.h"
-#include "insets/insetfloatlist.h"
#include "frontends/Dialogs.h"
#include "frontends/Alert.h"
#include "support/filetools.h"
#include "support/path.h"
#include "support/os.h"
+#include "support/tostr.h"
#include "support/lyxlib.h"
#include "support/FileInfo.h"
#include "support/lyxmanip.h"
#include <boost/bind.hpp>
#include <boost/tuple/tuple.hpp>
-#include "BoostFormat.h"
#include <fstream>
#include <iomanip>
namespace {
-const int LYX_FORMAT = 222;
+const int LYX_FORMAT = 223;
} // namespace anon
if (users)
users->buffer(0);
- if (!tmppath.empty()) {
- DestroyBufferTmpDir(tmppath);
+ if (!tmppath.empty() && destroyDir(tmppath) != 0) {
+ Alert::warning(_("Could not remove temporary directory"),
+ bformat(_("Could not remove the temporary directory %1$s"), tmppath));
}
paragraphs.clear();
string const Buffer::getLatexName(bool no_path) const
{
string const name = ChangeExtension(MakeLatexName(fileName()), ".tex");
- if (no_path)
- return OnlyFilename(name);
- else
- return name;
+ return no_path ? OnlyFilename(name) : name;
}
// 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.");
-#else
- _("The document uses an unknown textclass ")
- + unknown + _("-- substituting default.");
-#endif
- Alert::alert(_("Textclass error"), msg);
+ Alert::warning(_("Unknown document class"),
+ bformat(_("Using the default document class, because the "
+ " class %1$s is unknown."), unknown));
}
} // 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;
- int pos = 0;
Paragraph::depth_type depth = 0;
bool the_end_read = false;
- LyXFont font(LyXFont::ALL_INHERIT, params.language);
-
if (paragraphs.empty()) {
unknown_tokens += readHeader(lex);
if (!params.getLyXTextClass().load()) {
-#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."));
-#else
- Alert::alert(_("Textclass Loading Error!"),
- _("Can't load textclass ")
- + params.getLyXTextClass().name(),
- _("-- substituting default."));
-#endif
+ string theclass = params.getLyXTextClass().name();
+ Alert::error(_("Can't load document class"), bformat(
+ "Using the default document class, because the "
+ " class %1$s could not be loaded.", theclass));
params.textclass = 0;
}
} else {
// We are inserting into an existing document
- users->text->breakParagraph(users, paragraphs);
- pos = 0;
- markDirty();
+ users->text->breakParagraph(paragraphs);
// We don't want to adopt the parameters from the
// document we insert, so read them into a temporary buffer
continue;
}
- unknown_tokens += readToken(lex, paragraphs, pit, token, pos, depth, font);
+ 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");
- } else {
- s += tostr(unknown_layouts);
- s += _(" paragraphs");
- }
-#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 ");
+ string s;
if (unknown_tokens == 1) {
- s += _("one unknown token");
+ s = bformat(_("Encountered one unknown token when reading "
+ "the document %1$s."), fileName());
} else {
- s += tostr(unknown_tokens);
- s += _(" unknown tokens");
+ s = bformat(_("Encountered %1$s unknown tokens when reading "
+ "the document %2$s."), tostr(unknown_tokens), fileName());
}
-#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
+ Alert::warning(_("Document format failure"), s);
}
return the_end_read;
}
-int
-Buffer::readToken(LyXLex & lex, ParagraphList & pars,
- ParagraphList::iterator & pit,
- string const & token, int & pos,
- Paragraph::depth_type & depth,
- LyXFont & font)
+int Buffer::readParagraph(LyXLex & lex, string const & token,
+ ParagraphList & pars, ParagraphList::iterator & pit,
+ Paragraph::depth_type & depth)
{
static Change current_change;
int unknown = 0;
- // The order of the tags tested may seem unnatural, but this
- // has been done in order to reduce the number of string
- // comparisons needed to recognize a given token. This leads
- // on large documents like UserGuide to a reduction of a
- // factor 5! (JMarc)
- if (token[0] != '\\') {
- for (string::const_iterator cit = token.begin();
- cit != token.end(); ++cit) {
- pit->insertChar(pos, (*cit), font, current_change);
- ++pos;
- }
- } else if (token == "\\layout") {
- // reset the font as we start a new layout and if the font is
- // not ALL_INHERIT,document_language then it will be set to the
- // right values after this tag (Jug 20020420)
- font = LyXFont(LyXFont::ALL_INHERIT, params.language);
-
- lex.eatLine();
- string layoutname = lex.getString();
-
- LyXTextClass const & tclass = params.getLyXTextClass();
+ if (token == "\\layout") {
+ lex.pushToken(token);
- if (layoutname.empty()) {
- layoutname = tclass.defaultLayoutName();
- }
- bool hasLayout = tclass.hasLayout(layoutname);
- if (!hasLayout) {
- lyxerr << "Layout '" << layoutname << "' does not"
- << " exist in textclass '" << tclass.name()
- << "'." << endl;
- lyxerr << "Trying to use default layout instead."
- << endl;
- layoutname = tclass.defaultLayoutName();
- }
-
-#ifdef USE_CAPTION
- // The is the compability reading of layout caption.
- // It can be removed in LyX version 1.3.0. (Lgb)
- if (compare_ascii_no_case(layoutname, "caption") == 0) {
- // We expect that the par we are now working on is
- // really inside a InsetText inside a InsetFloat.
- // We also know that captions can only be
- // one paragraph. (Lgb)
-
- // We should now read until the next "\layout"
- // is reached.
- // This is probably not good enough, what if the
- // caption is the last par in the document (Lgb)
- istream & ist = lex.getStream();
- stringstream ss;
- string line;
- int begin = 0;
- while (true) {
- getline(ist, line);
- if (prefixIs(line, "\\layout")) {
- lex.pushToken(line);
- break;
- }
- if (prefixIs(line, "\\begin_inset"))
- ++begin;
- if (prefixIs(line, "\\end_inset")) {
- if (begin)
- --begin;
- else {
- lex.pushToken(line);
- break;
- }
- }
+ Paragraph par;
+ par.owningBuffer(*this);
+ par.params().depth(depth);
+ if (params.tracking_changes)
+ par.trackChanges();
+ LyXFont f(LyXFont::ALL_INHERIT, params.language);
+ par.setFont(0, f);
- ss << line << '\n';
- }
- // Now we should have the whole layout in ss
- // we should now be able to give this to the
- // caption inset.
- ss << "\\end_inset\n";
-
- // This seems like a bug in stringstream.
- // We really should be able to use ss
- // directly. (Lgb)
- istringstream is(ss.str());
- LyXLex tmplex(0, 0);
- tmplex.setStream(is);
- Inset * inset = new InsetCaption;
- inset->Read(this, tmplex);
- pit->InsertInset(pos, inset, font);
- ++pos;
- } else {
-#endif
- Paragraph * par = new Paragraph();
- par->layout(params.getLyXTextClass().defaultLayout());
- if (params.tracking_changes)
- par->trackChanges();
- pos = 0;
- par->layout(params.getLyXTextClass()[layoutname]);
- // Test whether the layout is obsolete.
- LyXLayout_ptr const & layout = par->layout();
- if (!layout->obsoleted_by().empty())
- par->layout(params.getLyXTextClass()[layout->obsoleted_by()]);
- par->params().depth(depth);
- // insert after
- if (pit != pars.end())
- ++pit;
- pit = pars.insert(pit, par);
-#if USE_CAPTION
- }
-#endif
+ // FIXME: goddamn InsetTabular makes us pass a Buffer
+ // not BufferParams
+ unknown += ::readParagraph(*this, par, lex);
- } else if (token == "\\end_inset") {
- lyxerr << "Solitary \\end_inset in line " << lex.getLineNo() << "\n"
- << "Missing \\begin_inset?.\n";
- // Simply ignore this. The insets do not have
- // to read this.
- // But insets should read it, it is a part of
- // the inset isn't it? Lgb.
- } else if (token == "\\begin_inset") {
- readInset(lex, pit, pos, font, current_change);
- } else if (token == "\\family") {
- lex.next();
- font.setLyXFamily(lex.getString());
- } else if (token == "\\series") {
- lex.next();
- font.setLyXSeries(lex.getString());
- } else if (token == "\\shape") {
- lex.next();
- font.setLyXShape(lex.getString());
- } else if (token == "\\size") {
- lex.next();
- font.setLyXSize(lex.getString());
- } else if (token == "\\lang") {
- lex.next();
- string const tok = lex.getString();
- Language const * lang = languages.getLanguage(tok);
- if (lang) {
- font.setLanguage(lang);
- } else {
- font.setLanguage(params.language);
- lex.printError("Unknown language `$$Token'");
- }
- } else if (token == "\\numeric") {
- lex.next();
- font.setNumber(font.setLyXMisc(lex.getString()));
- } else if (token == "\\emph") {
- lex.next();
- font.setEmph(font.setLyXMisc(lex.getString()));
- } else if (token == "\\bar") {
- lex.next();
- string const tok = lex.getString();
- // This is dirty, but gone with LyX3. (Asger)
- if (tok == "under")
- font.setUnderbar(LyXFont::ON);
- else if (tok == "no")
- font.setUnderbar(LyXFont::OFF);
- else if (tok == "default")
- font.setUnderbar(LyXFont::INHERIT);
- else
- lex.printError("Unknown bar font flag "
- "`$$Token'");
- } else if (token == "\\noun") {
- lex.next();
- font.setNoun(font.setLyXMisc(lex.getString()));
- } else if (token == "\\color") {
- lex.next();
- font.setLyXColor(lex.getString());
- } else if (token == "\\SpecialChar") {
- LyXLayout_ptr const & layout = pit->layout();
-
- // Insets don't make sense in a free-spacing context! ---Kayvan
- if (layout->free_spacing || pit->isFreeSpacing()) {
- if (lex.isOK()) {
- lex.next();
- string const next_token = lex.getString();
- if (next_token == "\\-") {
- pit->insertChar(pos, '-', font, current_change);
- } else if (next_token == "~") {
- pit->insertChar(pos, ' ', font, current_change);
- } else {
- lex.printError("Token `$$Token' "
- "is in free space "
- "paragraph layout!");
- --pos;
- }
- }
- } else {
- Inset * inset = new InsetSpecialChar;
- inset->read(this, lex);
- pit->insertInset(pos, inset, font, current_change);
- }
- ++pos;
- } else if (token == "\\i") {
- Inset * inset = new InsetLatexAccent;
- inset->read(this, lex);
- pit->insertInset(pos, inset, font, current_change);
- ++pos;
- } else if (token == "\\backslash") {
- pit->insertChar(pos, '\\', font, current_change);
- ++pos;
+ // insert after
+ if (pit != pars.end())
+ ++pit;
+ pit = pars.insert(pit, par);
} else if (token == "\\begin_deeper") {
++depth;
} else if (token == "\\end_deeper") {
if (!depth) {
- lex.printError("\\end_deeper: "
- "depth is already null");
- }
- else
- --depth;
- } else if (token == "\\noindent") {
- pit->params().noindent(true);
- } else if (token == "\\leftindent") {
- lex.nextToken();
- LyXLength value(lex.getString());
- pit->params().leftIndent(value);
- } else if (token == "\\fill_top") {
- pit->params().spaceTop(VSpace(VSpace::VFILL));
- } else if (token == "\\fill_bottom") {
- pit->params().spaceBottom(VSpace(VSpace::VFILL));
- } else if (token == "\\line_top") {
- pit->params().lineTop(true);
- } else if (token == "\\line_bottom") {
- pit->params().lineBottom(true);
- } else if (token == "\\pagebreak_top") {
- pit->params().pagebreakTop(true);
- } else if (token == "\\pagebreak_bottom") {
- pit->params().pagebreakBottom(true);
- } else if (token == "\\start_of_appendix") {
- pit->params().startOfAppendix(true);
- } else if (token == "\\paragraph_spacing") {
- lex.next();
- string const tmp = rtrim(lex.getString());
- if (tmp == "single") {
- pit->params().spacing(Spacing(Spacing::Single));
- } else if (tmp == "onehalf") {
- pit->params().spacing(Spacing(Spacing::Onehalf));
- } else if (tmp == "double") {
- pit->params().spacing(Spacing(Spacing::Double));
- } else if (tmp == "other") {
- lex.next();
- pit->params().spacing(Spacing(Spacing::Other,
- lex.getFloat()));
+ lex.printError("\\end_deeper: " "depth is already null");
} else {
- lex.printError("Unknown spacing token: '$$Token'");
+ --depth;
}
- } else if (token == "\\align") {
- int tmpret = lex.findToken(string_align);
- if (tmpret == -1)
- ++tmpret;
- int const tmpret2 = int(pow(2.0, tmpret));
- pit->params().align(LyXAlignment(tmpret2));
- } else if (token == "\\added_space_top") {
- lex.nextToken();
- VSpace value = VSpace(lex.getString());
- // only add the length when value > 0 or
- // with option keep
- if ((value.length().len().value() != 0) ||
- value.keep() ||
- (value.kind() != VSpace::LENGTH))
- pit->params().spaceTop(value);
- } else if (token == "\\added_space_bottom") {
- lex.nextToken();
- VSpace value = VSpace(lex.getString());
- // only add the length when value > 0 or
- // with option keep
- if ((value.length().len().value() != 0) ||
- value.keep() ||
- (value.kind() != VSpace::LENGTH))
- pit->params().spaceBottom(value);
- } else if (token == "\\labelwidthstring") {
- lex.eatLine();
- pit->params().labelWidthString(lex.getString());
- // do not delete this token, it is still needed!
- } else if (token == "\\newline") {
- pit->insertChar(pos, Paragraph::META_NEWLINE, font, current_change);
- ++pos;
- } else if (token == "\\LyXTable") {
- Inset * inset = new InsetTabular(*this);
- inset->read(this, lex);
- pit->insertInset(pos, inset, font, current_change);
- ++pos;
- } else if (token == "\\bibitem") { // ale970302
- InsetCommandParams p("bibitem", "dummy");
- InsetBibitem * inset = new InsetBibitem(p);
- inset->read(this, lex);
- pit->insertInset(pos, inset, font, current_change);
- ++pos;
- } else if (token == "\\hfill") {
- pit->insertInset(pos, new InsetHFill(),
- LyXFont(LyXFont::ALL_INHERIT, params.language));
- ++pos;
- } else if (token == "\\change_unchanged") {
- // Hack ! Needed for empty paragraphs :/
- if (!pos)
- pit->cleanChanges();
- current_change = Change(Change::UNCHANGED);
- } else if (token == "\\change_inserted") {
- lex.nextToken();
- istringstream istr(lex.getString());
- int aid;
- lyx::time_type ct;
- istr >> aid;
- istr >> ct;
- current_change = Change(Change::INSERTED, params.author_ids[aid], ct);
- } else if (token == "\\change_deleted") {
- lex.nextToken();
- istringstream istr(lex.getString());
- int aid;
- lyx::time_type ct;
- istr >> aid;
- istr >> ct;
- current_change = Change(Change::DELETED, params.author_ids[aid], ct);
} else {
- // This should be insurance for the future: (Asger)
++unknown;
- lex.eatLine();
-#if USE_BOOST_FORMAT
- boost::format fmt(_("Unknown token: %1$s %2$s\n"));
- fmt % token % lex.text();
- string const s = fmt.str();
-#else
- string const s = _("Unknown token: ") + token
- + ' ' + lex.text() + '\n';
-#endif
- // we can do this here this way because we're actually reading
- // the buffer and don't care about LyXText right now.
- InsetError * new_inset = new InsetError(s);
- pit->insertInset(pos, new_inset, LyXFont(LyXFont::ALL_INHERIT,
- params.language));
-
}
-
return unknown;
}
// 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 {
}
-void Buffer::readInset(LyXLex & lex, ParagraphList::iterator pit,
- int & pos, LyXFont & font, Change current_change)
+bool Buffer::readFile(LyXLex & lex, string const & filename)
{
- // consistency check
- if (lex.getString() != "\\begin_inset") {
- lyxerr << "Buffer::readInset: Consistency check failed."
- << endl;
- }
+ bool ret = readFile(lex, filename, paragraphs.begin());
- Inset * inset = 0;
+ // 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);
+
+ return ret;
+}
- lex.next();
- string const tmptok = lex.getString();
-
- // test the different insets
- if (tmptok == "LatexCommand") {
- InsetCommandParams inscmd;
- inscmd.read(lex);
-
- string const cmdName = inscmd.getCmdName();
-
- // This strange command allows LyX to recognize "natbib" style
- // citations: citet, citep, Citet etc.
- if (compare_ascii_no_case(cmdName.substr(0,4), "cite") == 0) {
- inset = new InsetCitation(inscmd);
- } else if (cmdName == "bibitem") {
- lex.printError("Wrong place for bibitem");
- inset = new InsetBibitem(inscmd);
- } else if (cmdName == "BibTeX") {
- inset = new InsetBibtex(inscmd);
- } else if (cmdName == "index") {
- inset = new InsetIndex(inscmd);
- } else if (cmdName == "include") {
- inset = new InsetInclude(inscmd, *this);
- } else if (cmdName == "label") {
- inset = new InsetLabel(inscmd);
- } else if (cmdName == "url"
- || cmdName == "htmlurl") {
- inset = new InsetUrl(inscmd);
- } else if (cmdName == "ref"
- || cmdName == "pageref"
- || cmdName == "vref"
- || cmdName == "vpageref"
- || cmdName == "prettyref") {
- if (!inscmd.getOptions().empty()
- || !inscmd.getContents().empty()) {
- inset = new InsetRef(inscmd, *this);
- }
- } else if (cmdName == "tableofcontents") {
- inset = new InsetTOC(inscmd);
- } else if (cmdName == "listofalgorithms") {
- inset = new InsetFloatList("algorithm");
- } else if (cmdName == "listoffigures") {
- inset = new InsetFloatList("figure");
- } else if (cmdName == "listoftables") {
- inset = new InsetFloatList("table");
- } else if (cmdName == "printindex") {
- inset = new InsetPrintIndex(inscmd);
- } else if (cmdName == "lyxparent") {
- inset = new InsetParent(inscmd, *this);
- }
- } else {
- if (tmptok == "Quotes") {
- inset = new InsetQuotes;
- } else if (tmptok == "External") {
- inset = new InsetExternal;
- } else if (tmptok == "FormulaMacro") {
- inset = new InsetFormulaMacro;
- } else if (tmptok == "Formula") {
- inset = new InsetFormula;
- } else if (tmptok == "Graphics") {
- inset = new InsetGraphics;
- } else if (tmptok == "Note") {
- inset = new InsetNote(params);
- } else if (tmptok == "Include") {
- InsetCommandParams p("Include");
- inset = new InsetInclude(p, *this);
- } else if (tmptok == "ERT") {
- inset = new InsetERT(params);
- } else if (tmptok == "Tabular") {
- inset = new InsetTabular(*this);
- } else if (tmptok == "Text") {
- inset = new InsetText(params);
- } else if (tmptok == "Foot") {
- inset = new InsetFoot(params);
- } else if (tmptok == "Marginal") {
- inset = new InsetMarginal(params);
- } else if (tmptok == "OptArg") {
- inset = new InsetOptArg(params);
- } else if (tmptok == "Minipage") {
- inset = new InsetMinipage(params);
- } else if (tmptok == "Float") {
- lex.next();
- string tmptok = lex.getString();
- inset = new InsetFloat(params, tmptok);
- } else if (tmptok == "Wrap") {
- lex.next();
- string tmptok = lex.getString();
- inset = new InsetWrap(params, tmptok);
-#if 0
- } else if (tmptok == "List") {
- inset = new InsetList;
- } else if (tmptok == "Theorem") {
- inset = new InsetList;
-#endif
- } else if (tmptok == "Caption") {
- inset = new InsetCaption(params);
- } else if (tmptok == "FloatList") {
- inset = new InsetFloatList;
- }
- if (inset)
- inset->read(this, lex);
+// 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;
}
- if (inset) {
- pit->insertInset(pos, inset, font, current_change);
- ++pos;
+ 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;
+ }
-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;
- }
+ 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;
}
- bool the_end = readBody(lex, pit);
- params.setPaperStuff();
-
- if (!the_end) {
- Alert::alert(_("Warning!"),
- _("Reading of document is not complete"),
- _("Maybe the document is truncated"));
+ 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;
}
- return true;
- } else { // "\\lyxformat" not found
- Alert::alert(_("ERROR!"), _("Not a LyX file!"));
+ 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;
}
// this will write out all the paragraphs
// using recursive descent.
- ParagraphList::iterator pit = paragraphs.begin();
- ParagraphList::iterator pend = paragraphs.end();
+ ParagraphList::const_iterator pit = paragraphs.begin();
+ ParagraphList::const_iterator pend = paragraphs.end();
for (; pit != pend; ++pit)
pit->write(this, ofs, params, depth);
/* noindent ? */
/* what about the alignment */
-// } else {
-// lyxerr << "Should this ever happen?" << endl;
-// }
// linelen <= 0 is special and means we don't have paragraph breaks
}
break;
- case Paragraph::META_NEWLINE:
- if (linelen > 0) {
- buffer << word << "\n";
- word.erase();
-
- pair<int, string> p = addDepth(depth,
- ltype_depth);
- buffer << p.second;
- currlinelen = p.first;
- }
- break;
-
default:
if (c == ' ') {
if (linelen > 0 &&
{
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::err_alert(_("Error: Cannot write file:"), fname);
+ string const file = MakeDisplayPath(fname, 50);
+ string text = bformat(_("Could not save the document\n%1$s."), file);
+ Alert::error(_("Could not save document"), text);
return;
}
writeFileAscii(ofs, linelen);
void Buffer::makeLaTeXFile(string const & fname,
string const & original_path,
- bool nice, bool only_body, bool only_preamble)
+ LatexRunParams const & runparams,
+ bool only_body, bool only_preamble)
{
lyxerr[Debug::LATEX] << "makeLaTeXFile..." << endl;
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::err_alert(_("Error: Cannot open file: "), fname);
+ string const file = MakeDisplayPath(fname, 50);
+ string text = bformat(_("Could not open the specified document\n%1$s."),
+ file);
+ Alert::error(_("Could not open file"), text);
return;
}
- makeLaTeXFile(ofs, original_path, nice, only_body, only_preamble);
+ makeLaTeXFile(ofs, original_path,
+ runparams, only_body, only_preamble);
ofs.close();
if (ofs.fail()) {
void Buffer::makeLaTeXFile(ostream & os,
string const & original_path,
- bool nice, bool only_body, bool only_preamble)
+ LatexRunParams const & runparams_in,
+ bool only_body, bool only_preamble)
{
- niceFile = nice; // this will be used by Insetincludes.
+ LatexRunParams runparams = runparams_in;
+ niceFile = runparams.nice; // this will be used by Insetincludes.
// validate the buffer.
lyxerr[Debug::LATEX] << " Validating buffer..." << endl;
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) {
+ if (!only_body && runparams.nice) {
os << "%% " << lyx_docversion << " created this file. "
"For more info, see http://www.lyx.org/.\n"
"%% Do not edit unless you really know what "
// original_path is set. This is done for usual tex-file, but not
// for nice-latex-file. (Matthias 250696)
if (!only_body) {
- if (!nice) {
+ if (!runparams.nice) {
// code for usual, NOT nice-latex-file
os << "\\batchmode\n"; // changed
// from \nonstopmode
}
// Write the preamble
- params.writeLaTeX(os, features, texrow);
+ runparams.use_babel = params.writeLaTeX(os, features, texrow);
if (only_preamble)
return;
texrow.newline();
}
- latexParagraphs(this, paragraphs, paragraphs.begin(), paragraphs.end(), os, texrow);
+ latexParagraphs(this, paragraphs, os, texrow, runparams);
// add this just in case after all the paragraphs
os << endl;
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::alert(_("LYX_ERROR:"), _("Cannot write file"), fname);
+ string const file = MakeDisplayPath(fname, 50);
+ string text = bformat(_("Could not save the specified document\n%1$s.\n"),
+ file);
+ 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();
+ users->resetErrorList();
+
+ 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
// we want this to be true outside previews (for insetexternal)
niceFile = true;
+
+ users->showErrorList(_("LinuxDoc"));
}
// 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*/,
- string const & /*message*/) const
-{
-#ifdef WITH_WARNINGS
-#warning This is wrong we cannot insert an inset like this!!!
- // I guess this was Jose' so I explain you more or less why this
- // is wrong. This way you insert something in the paragraph and
- // don't tell it to LyXText (row rebreaking and undo handling!!!)
- // I deactivate this code, have a look at BufferView::insertErrors
- // how you should do this correctly! (Jug 20020315)
-#endif
-#if 0
- // insert an error marker in text
- InsetError * new_inset = new InsetError(message);
- par->insertInset(pos, new_inset, LyXFont(LyXFont::ALL_INHERIT,
- params.language));
-#endif
+void Buffer::sgmlError(ParagraphList::iterator pit, int pos,
+ string const & message) const
+{
+ users->addError(ErrorItem(message, string(), pit->id(), pos, pos));
}
{
ofstream ofs(fname.c_str());
if (!ofs) {
- Alert::alert(_("LYX_ERROR:"), _("Cannot write file"), fname);
+ string const file = MakeDisplayPath(fname, 50);
+ string text = bformat(_("Could not save the specified document\n%1$s.\n"),
+ file);
+ 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) {
+ users->resetErrorList();
+
+ 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
// we want this to be true outside previews (for insetexternal)
niceFile = true;
+ users->showErrorList(_("DocBook"));
}
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()) {
Path p(path); // path to LaTeX file
users->owner()->message(_("Running chktex..."));
- // Remove all error insets
- bool const removedErrorInsets = users->removeAutoInsets();
-
// Generate the LaTeX file if neccessary
- makeLaTeXFile(name, org_path, false);
+ LatexRunParams runparams;
+ runparams.flavor = LatexRunParams::LATEX;
+ runparams.nice = false;
+ makeLaTeXFile(name, org_path, runparams);
TeXErrors terr;
Chktex chktex(lyxrc.chktex_command, name, filePath());
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);
+ ErrorList el (*this, terr);
+ users->setErrorList(el);
+ users->showErrorList(_("ChkTeX"));
}
- // if we removed error insets before we ran chktex or if we inserted
- // error insets after we ran chktex, this must be run:
- if (removedErrorInsets || res) {
-#warning repaint needed here, or do you mean update() ?
- users->repaint();
- users->fitCursor();
- }
users->owner()->busy(false);
return res;
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
+ParIterator Buffer::getParFromID(int id) const
{
- if (id < 0)
- return 0;
+#warning FIXME: const correctness! (Andre)
+ ParIterator it = const_cast<Buffer*>(this)->par_iterator_begin();
+ ParIterator end = const_cast<Buffer*>(this)->par_iterator_end();
- // why should we allow < 0 ??
- //lyx::Assert(id >= 0);
+#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 end;
+ }
- ParConstIterator it(par_iterator_begin());
- ParConstIterator end(par_iterator_end());
+ for (; it != end; ++it)
+ if ((*it)->id() == id)
+ return it;
- for (; it != end; ++it) {
- // go on then, show me how to remove
- // the cast
- if ((*it)->id() == id) {
- return const_cast<Paragraph*>(*it);
- }
+ return end;
+}
+
+
+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;
}
- return 0;
+ for (; it != end; ++it)
+ if ((*it)->id() == id)
+ return true;
+
+ return false;
}
ParIterator Buffer::par_iterator_begin()
{
- return ParIterator(&*(paragraphs.begin()));
+ return ParIterator(paragraphs.begin(), paragraphs);
}
ParIterator Buffer::par_iterator_end()
{
- return ParIterator();
+ return ParIterator(paragraphs.end(), paragraphs);
}
ParConstIterator Buffer::par_iterator_begin() const
{
- return ParConstIterator(&*(paragraphs.begin()));
+ return ParConstIterator(const_cast<ParagraphList&>(paragraphs).begin(), paragraphs);
}
ParConstIterator Buffer::par_iterator_end() const
{
- return ParConstIterator();
+ return ParConstIterator(const_cast<ParagraphList&>(paragraphs).end(), paragraphs);
}
}
+string const Buffer::B_(string const & l10n) const
+{
+ if (messages_.get()) {
+ return messages_->get(l10n);
+ }
+
+ return _(l10n);
+}
+
+
bool Buffer::isClean() const
{
return lyx_clean;
Buffer::inset_iterator::inset_iterator()
- : pit(0), pend(0)
+ : pit(), pend()
{}
}
-Paragraph * Buffer::inset_iterator::getPar()
+ParagraphList::iterator Buffer::inset_iterator::getPar() const
{
- return &(*pit);
+ return pit;
}