#include "Bullet.h"
#include "Chktex.h"
#include "debug.h"
+#include "encoding.h"
#include "errorlist.h"
#include "exporter.h"
#include "format.h"
#include "insets/insetinclude.h"
#include "insets/insettext.h"
+#include "mathed/math_macrotemplate.h"
+#include "mathed/math_macrotable.h"
+#include "mathed/math_support.h"
+
#include "frontends/Alert.h"
#include "graphics/Previews.h"
#include "support/FileInfo.h"
#include "support/filetools.h"
-#include "support/gzstream.h"
+#ifdef USE_COMPRESSION
+# include "support/gzstream.h"
+#endif
#include "support/lyxlib.h"
#include "support/os.h"
#include "support/path.h"
#include "support/textutils.h"
-#include "support/tostr.h"
-#include "support/std_sstream.h"
+#include "support/convert.h"
#include <boost/bind.hpp>
+#include <utime.h>
+
#include <iomanip>
#include <stack>
+#include <sstream>
+#include <fstream>
-#include <utime.h>
using lyx::pos_type;
-using lyx::par_type;
+using lyx::pit_type;
using lyx::support::AddName;
-using lyx::support::atoi;
using lyx::support::bformat;
using lyx::support::ChangeExtension;
using lyx::support::cmd_ret;
using lyx::support::destroyDir;
using lyx::support::FileInfo;
using lyx::support::FileInfo;
-using lyx::support::getExtFromContents;
+using lyx::support::getFormatFromContents;
using lyx::support::IsDirWriteable;
using lyx::support::IsFileWriteable;
using lyx::support::LibFileSearch;
using std::ifstream;
using std::ios;
+using std::map;
using std::ostream;
using std::ostringstream;
using std::ofstream;
namespace {
-const int LYX_FORMAT = 232;
+int const LYX_FORMAT = 239;
} // namespace anon
typedef std::map<string, bool> DepClean;
-struct Buffer::Impl
+class Buffer::Impl
{
+public:
Impl(Buffer & parent, string const & file, bool readonly);
limited_stack<Undo> undostack;
/// our LyXText that should be wrapped in an InsetText
InsetText inset;
+
+ ///
+ MacroTable macros;
};
}
-string const Buffer::getLatexName(bool no_path) const
+string const Buffer::getLatexName(bool const no_path) const
{
string const name = ChangeExtension(MakeLatexName(fileName()), ".tex");
return no_path ? OnlyFilename(name) : name;
}
-void Buffer::setReadonly(bool flag)
+void Buffer::setReadonly(bool const flag)
{
if (pimpl_->read_only != flag) {
pimpl_->read_only = flag;
int Buffer::readHeader(LyXLex & lex)
{
int unknown_tokens = 0;
+ int line = -1;
+ int begin_header_line = -1;
while (lex.isOK()) {
- lex.nextToken();
+ lex.next();
string const token = lex.getString();
if (token.empty())
if (token == "\\end_header")
break;
+ ++line;
+ if (token == "\\begin_header") {
+ begin_header_line = line;
+ continue;
+ }
+
lyxerr[Debug::PARSER] << "Handling header token: `"
<< token << '\'' << endl;
-
string unknown = params().readToken(lex, token);
if (!unknown.empty()) {
- if (unknown[0] != '\\') {
+ if (unknown[0] != '\\' && token == "\\textclass") {
unknownClass(unknown);
} else {
++unknown_tokens;
}
}
}
+ if (begin_header_line) {
+ string const s = _("\\begin_header is missing");
+ error(ErrorItem(_("Header error"), s, -1, 0, 0));
+ }
return unknown_tokens;
}
// Uwe C. Schroeder
// changed to be public and have one parameter
// Returns false if "\end_document" is not read (Asger)
-bool Buffer::readBody(LyXLex & lex)
+bool Buffer::readDocument(LyXLex & lex)
{
+ lex.next();
+ string const token = lex.getString();
+ if (token != "\\begin_document") {
+ string const s = _("\\begin_document is missing");
+ error(ErrorItem(_("Header error"), s, -1, 0, 0));
+ }
+
if (paragraphs().empty()) {
readHeader(lex);
if (!params().getLyXTextClass().load()) {
// needed to insert the selection
void Buffer::insertStringAsLines(ParagraphList & pars,
- par_type & par, pos_type & pos,
- LyXFont const & fn, string const & str)
+ pit_type & par, pos_type & pos,
+ LyXFont const & fn, string const & str, bool autobreakrows)
{
LyXLayout_ptr const & layout = pars[par].layout();
pars[par].checkInsertChar(font);
// insert the string, don't insert doublespace
bool space_inserted = true;
- bool autobreakrows = !pars[par].inInset() ||
- static_cast<InsetText *>(pars[par].inInset())->getAutoBreakRows();
for (string::const_iterator cit = str.begin();
cit != str.end(); ++cit) {
if (*cit == '\n') {
bool Buffer::readFile(string const & filename)
{
// Check if the file is compressed.
- string const format = getExtFromContents(filename);
+ string const format = getFormatFromContents(filename);
if (format == "gzip" || format == "zip" || format == "compress") {
params().compressed = true;
}
}
-bool Buffer::readFile(string const & filename, par_type pit)
+bool Buffer::readFile(string const & filename, pit_type const pit)
{
LyXLex lex(0, 0);
lex.setFile(filename);
}
-void Buffer::fully_loaded(bool value)
+void Buffer::fully_loaded(bool const value)
{
pimpl_->file_fully_loaded = value;
}
-bool Buffer::readFile(LyXLex & lex, string const & filename, par_type pit)
+bool Buffer::readFile(LyXLex & lex, string const & filename, pit_type const pit)
{
BOOST_ASSERT(!filename.empty());
return false;
}
- lex.eatLine();
+ lex.next();
string tmp_format = lex.getString();
//lyxerr << "LyX Format: `" << tmp_format << '\'' << endl;
// if present remove ".," from string.
int file_format = strToInt(tmp_format);
//lyxerr << "format: " << file_format << endl;
- if (file_format > LYX_FORMAT) {
- Alert::warning(_("Document format failure"),
- bformat(_("%1$s was created with a newer"
- " version of LyX. This is likely to"
- " cause problems."),
- filename));
- } else if (file_format < LYX_FORMAT) {
+ if (file_format != LYX_FORMAT) {
string const tmpfile = tempName();
if (tmpfile.empty()) {
Alert::error(_("Conversion failed"),
filename));
return false;
}
- string command = LibFileSearch("lyx2lyx", "lyx2lyx");
+ string command =
+ "python " + LibFileSearch("lyx2lyx", "lyx2lyx");
if (command.empty()) {
Alert::error(_("Conversion script not found"),
bformat(_("%1$s is from an earlier"
return false;
}
command += " -t"
- + tostr(LYX_FORMAT)
+ + convert<string>(LYX_FORMAT)
+ " -o " + tmpfile + ' '
+ QuoteName(filename);
lyxerr[Debug::INFO] << "Running '"
}
- bool the_end = readBody(lex);
- params().setPaperStuff();
-
-#warning Look here!
-#if 0
- if (token == "\\end_document")
- the_end_read = true;
-
- if (!the_end) {
+ if (readDocument(lex)) {
Alert::error(_("Document format failure"),
bformat(_("%1$s ended unexpectedly, which means"
" that it is probably corrupted."),
filename));
}
-#endif
+
+ //lyxerr << "removing " << MacroTable::localMacros().size()
+ // << " temporary macro entries" << endl;
+ //MacroTable::localMacros().clear();
+ params().setPaperStuff();
+
pimpl_->file_fully_loaded = true;
return true;
}
s = fileName() + '~';
if (!lyxrc.backupdir_path.empty())
s = AddName(lyxrc.backupdir_path,
- subst(os::slashify_path(s),'/','!'));
+ subst(os::internal_path(s),'/','!'));
// Rename is the wrong way of making a backup,
// this is the correct way.
if (finfo.exist() && !finfo.writable())
return false;
- bool retval;
+ bool retval = false;
if (params().compressed) {
+#ifdef USE_COMPRESSION
gz::ogzstream ofs(fname.c_str());
if (!ofs)
return false;
retval = do_writeFile(ofs);
-
+#else
+ return false;
+#endif
} else {
ofstream ofs(fname.c_str());
if (!ofs)
// write out a comment in the top of the file
ofs << "#LyX " << lyx_version
<< " created this file. For more info see http://www.lyx.org/\n"
- << "\\lyxformat " << LYX_FORMAT << "\n";
+ << "\\lyxformat " << LYX_FORMAT << "\n"
+ << "\\begin_document\n";
// now write out the buffer parameters.
+ ofs << "\\begin_header\n";
params().writeFile(ofs);
-
ofs << "\\end_header\n";
// write the text
+ ofs << "\n\\begin_body\n";
text().write(*this, ofs);
+ ofs << "\n\\end_body\n";
// Write marker that shows file is complete
- ofs << "\n\\end_document" << endl;
+ ofs << "\\end_document" << endl;
// Shouldn't really be needed....
//ofs.close();
void Buffer::makeLaTeXFile(ostream & os,
string const & original_path,
OutputParams const & runparams_in,
- bool output_preamble, bool output_body)
+ bool const output_preamble, bool const output_body)
{
OutputParams runparams = runparams_in;
lyxerr[Debug::LATEX] << " Buffer validation done." << endl;
texrow().reset();
+
// The starting paragraph of the coming rows is the
// first paragraph of the document. (Asger)
texrow().start(paragraphs().begin()->id(), 0);
void Buffer::makeLinuxDocFile(string const & fname,
OutputParams const & runparams,
- bool body_only)
+ bool const body_only)
{
ofstream ofs;
if (!openFileWrite(ofs, fname))
LyXTextClass const & tclass = params().getLyXTextClass();
- string top_element = tclass.latexname();
+ string const & top_element = tclass.latexname();
if (!body_only) {
ofs << tclass.class_header();
ofs << ">\n\n";
if (params().options.empty())
- sgml::openTag(ofs, 0, false, top_element);
+ sgml::openTag(ofs, top_element);
else {
string top = top_element;
top += ' ';
top += params().options;
- sgml::openTag(ofs, 0, false, top);
+ sgml::openTag(ofs, top);
}
}
if (!body_only) {
ofs << "\n\n";
- sgml::closeTag(ofs, 0, false, top_element);
+ sgml::closeTag(ofs, top_element);
}
ofs.close();
void Buffer::makeDocBookFile(string const & fname,
OutputParams const & runparams,
- bool only_body)
+ bool const only_body)
{
ofstream ofs;
if (!openFileWrite(ofs, fname))
texrow().reset();
LyXTextClass const & tclass = params().getLyXTextClass();
- string top_element = tclass.latexname();
+ string const & top_element = tclass.latexname();
if (!only_body) {
- ofs << subst(tclass.class_header(), "#", top_element);
+ if (runparams.flavor == OutputParams::XML)
+ ofs << "<?xml version=\"1.0\" encoding=\""
+ << params().language->encoding()->Name() << "\"?>\n";
+
+ ofs << "<!DOCTYPE " << top_element << " ";
+
+ if (! tclass.class_header().empty()) ofs << tclass.class_header();
+ else if (runparams.flavor == OutputParams::XML)
+ ofs << "PUBLIC \"-//OASIS//DTD DocBook XML//EN\" "
+ << "\"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd\"";
+ else
+ ofs << " PUBLIC \"-//OASIS//DTD DocBook V4.2//EN\"";
string preamble = params().preamble;
+ if (runparams.flavor != OutputParams::XML ) {
+ preamble += "<!ENTITY % output.print.png \"IGNORE\">\n";
+ preamble += "<!ENTITY % output.print.pdf \"IGNORE\">\n";
+ preamble += "<!ENTITY % output.print.eps \"IGNORE\">\n";
+ preamble += "<!ENTITY % output.print.bmp \"IGNORE\">\n";
+ }
+
string const name = runparams.nice ? ChangeExtension(pimpl_->filename, ".sgml")
: fname;
preamble += features.getIncludedFiles(name);
string top = top_element;
top += " lang=\"";
- top += params().language->code();
+ if (runparams.flavor == OutputParams::XML)
+ top += params().language->code();
+ else
+ top += params().language->code().substr(0,2);
top += '"';
if (!params().options.empty()) {
top += ' ';
top += params().options;
}
- sgml::openTag(ofs, 0, false, top);
- ofs << "<!-- SGML/XML file was created by LyX " << lyx_version
+ ofs << "<!-- " << ((runparams.flavor == OutputParams::XML)? "XML" : "SGML")
+ << " file was created by LyX " << lyx_version
<< "\n See http://www.lyx.org/ for more information -->\n";
params().getLyXTextClass().counters().reset();
- docbookParagraphs(*this, paragraphs(), ofs, runparams);
- ofs << "\n\n";
- sgml::closeTag(ofs, 0, false, top_element);
+ sgml::openTag(ofs, top);
+ ofs << '\n';
+ docbookParagraphs(paragraphs(), *this, ofs, runparams);
+ sgml::closeTag(ofs, top_element);
ofs.close();
if (ofs.fail())
TeXErrors terr;
Chktex chktex(lyxrc.chktex_command, name, filePath());
- int res = chktex.run(terr); // run chktex
+ int const res = chktex.run(terr); // run chktex
if (res == -1) {
Alert::error(_("chktex failure"),
}
-void Buffer::getLabelList(std::vector<string> & list) const
+void Buffer::getLabelList(vector<string> & list) const
{
/// if this is a child document and the parent is already loaded
/// Use the parent's list instead [ale990407]
// This is also a buffer property (ale)
-void Buffer::fillWithBibKeys(std::vector<std::pair<string, string> > & keys)
+void Buffer::fillWithBibKeys(vector<pair<string, string> > & keys)
const
{
/// if this is a child document and the parent is already loaded
}
for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
- if (it->lyxCode() == InsetOld::BIBTEX_CODE) {
+ if (it->lyxCode() == InsetBase::BIBTEX_CODE) {
InsetBibtex const & inset =
dynamic_cast<InsetBibtex const &>(*it);
inset.fillWithBibKeys(*this, keys);
- } else if (it->lyxCode() == InsetOld::INCLUDE_CODE) {
+ } else if (it->lyxCode() == InsetBase::INCLUDE_CODE) {
InsetInclude const & inset =
dynamic_cast<InsetInclude const &>(*it);
inset.fillWithBibKeys(*this, keys);
- } else if (it->lyxCode() == InsetOld::BIBITEM_CODE) {
+ } else if (it->lyxCode() == InsetBase::BIBITEM_CODE) {
InsetBibitem const & inset =
dynamic_cast<InsetBibitem const &>(*it);
string const key = inset.getContents();
bool Buffer::isDepClean(string const & name) const
{
- DepClean::const_iterator it = pimpl_->dep_clean.find(name);
+ DepClean::const_iterator const it = pimpl_->dep_clean.find(name);
if (it == pimpl_->dep_clean.end())
return true;
return it->second;
void Buffer::changeLanguage(Language const * from, Language const * to)
{
+ BOOST_ASSERT(from);
+ BOOST_ASSERT(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)
- it->changeLanguage(params(), from, to);
+ for_each(par_iterator_begin(),
+ par_iterator_end(),
+ bind(&Paragraph::changeLanguage, _1, params(), from, to));
}
void Buffer::updateDocLang(Language const * nlang)
{
+ BOOST_ASSERT(nlang);
+
pimpl_->messages.reset(new Messages(nlang->code()));
}
}
-ParIterator Buffer::getParFromID(int id) const
+ParIterator Buffer::getParFromID(int const id) const
{
ParConstIterator it = par_iterator_begin();
- ParConstIterator end = par_iterator_end();
+ ParConstIterator const end = par_iterator_end();
if (id < 0) {
// John says this is called with id == -1 from undo
}
-bool Buffer::hasParWithID(int id) const
+bool Buffer::hasParWithID(int const id) const
{
- ParConstIterator it = par_iterator_begin();
- ParConstIterator end = 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;
+ ParConstIterator const it = getParFromID(id);
+ return it != par_iterator_end();
}
}
+#ifdef WITH_WARNINGS
+#warning this function should be moved to buffer_pimpl.C
+#endif
void Buffer::markDirty()
{
if (pimpl_->lyx_clean) {
return this;
}
+
+
+MacroData const & Buffer::getMacro(std::string const & name) const
+{
+ return pimpl_->macros.get(name);
+}
+
+
+bool Buffer::hasMacro(string const & name) const
+{
+ return pimpl_->macros.has(name);
+}
+
+
+void Buffer::insertMacro(string const & name, MacroData const & data)
+{
+ MacroTable::globalMacros().insert(name, data);
+ pimpl_->macros.insert(name, data);
+}
+
+
+void Buffer::buildMacros()
+{
+ // Start with global table.
+ pimpl_->macros = MacroTable::globalMacros();
+
+ // Now add our own.
+ ParagraphList & pars = text().paragraphs();
+ for (size_t i = 0, n = pars.size(); i != n; ++i) {
+ //lyxerr << "searching main par " << i
+ // << " for macro definitions" << std::endl;
+ InsetList::iterator it = pars[i].insetlist.begin();
+ InsetList::iterator end = pars[i].insetlist.end();
+ for ( ; it != end; ++it) {
+ //lyxerr << "found inset code " << it->inset->lyxCode() << std::endl;
+ if (it->inset->lyxCode() == InsetBase::MATHMACRO_CODE) {
+ MathMacroTemplate & mac
+ = static_cast<MathMacroTemplate &>(*it->inset);
+ insertMacro(mac.name(), mac.asMacroData());
+ }
+ }
+ }
+}