#include "buffer.h"
#include "bufferlist.h"
-#include "lyx_main.h"
+#include "counters.h"
#include "LyXAction.h"
#include "lyxrc.h"
#include "lyxlex.h"
#include "ParagraphParameters.h"
#include "iterators.h"
#include "lyxtextclasslist.h"
+#include "sgml.h"
#include "mathed/formulamacro.h"
#include "mathed/formula.h"
#include "support/lyxmanip.h"
#include "support/lyxalgo.h" // for lyx::count
+#include <boost/bind.hpp>
+#include <boost/tuple/tuple.hpp>
+
#include <fstream>
#include <iomanip>
#include <map>
#include <sys/types.h>
#include <utime.h>
-
#ifdef HAVE_LOCALE
#include <locale>
#endif
using std::set;
using std::stack;
using std::list;
+using std::for_each;
using lyx::pos_type;
using lyx::textclass_type;
// all these externs should eventually be removed.
extern BufferList bufferlist;
-extern LyXAction lyxaction;
-
namespace {
const int LYX_FORMAT = 220;
} // namespace anon
-extern int tex_code_break_column;
-
-
Buffer::Buffer(string const & file, bool ronly)
- : paragraph(0), niceFile(true), lyx_clean(true), bak_clean(true),
+ : niceFile(true), lyx_clean(true), bak_clean(true),
unnamed(false), dep_clean(0), read_only(ronly),
- filename_(file), users(0)
+ filename_(file), users(0), ctrs(new Counters)
{
lyxerr[Debug::INFO] << "Buffer::Buffer()" << endl;
// filename = file;
filepath_ = OnlyPath(file);
-// paragraph = 0;
// lyx_clean = true;
// bak_clean = true;
// dep_clean = 0;
DestroyBufferTmpDir(tmppath);
}
- Paragraph * par = paragraph;
- Paragraph * tmppar;
- while (par) {
- tmppar = par->next();
- delete par;
- par = tmppar;
- }
- paragraph = 0;
+ paragraphs.clear();
// Remove any previewed LaTeX snippets assocoated with this buffer.
grfx::Previews::get().removeLoader(this);
if (read_only != flag) {
read_only = flag;
updateTitles();
- users->owner()->getDialogs()->updateBufferDependent(false);
+ users->owner()->getDialogs().updateBufferDependent(false);
}
}
if (!first_par)
first_par = par;
- paragraph = first_par;
+ paragraphs.set(first_par);
if (unknown_layouts > 0) {
string s = _("Couldn't set the layout for ");
int tmpret = lex.findToken(string_paragraph_separation);
if (tmpret == -1)
++tmpret;
- if (tmpret != LYX_LAYOUT_DEFAULT)
- params.paragraph_separation =
- static_cast<BufferParams::PARSEP>(tmpret);
+ params.paragraph_separation =
+ static_cast<BufferParams::PARSEP>(tmpret);
} else if (token == "\\defskip") {
lex.nextToken();
params.defskip = VSpace(lex.getString());
int tmpret = lex.findToken(string_quotes_language);
if (tmpret == -1)
++tmpret;
- if (tmpret != LYX_LAYOUT_DEFAULT) {
- InsetQuotes::quote_language tmpl =
- InsetQuotes::EnglishQ;
- switch (tmpret) {
- case 0:
- tmpl = InsetQuotes::EnglishQ;
- break;
- case 1:
- tmpl = InsetQuotes::SwedishQ;
- break;
- case 2:
- tmpl = InsetQuotes::GermanQ;
- break;
- case 3:
- tmpl = InsetQuotes::PolishQ;
- break;
- case 4:
- tmpl = InsetQuotes::FrenchQ;
- break;
- case 5:
- tmpl = InsetQuotes::DanishQ;
- break;
- }
- params.quotes_language = tmpl;
+ InsetQuotes::quote_language tmpl =
+ InsetQuotes::EnglishQ;
+ switch (tmpret) {
+ case 0:
+ tmpl = InsetQuotes::EnglishQ;
+ break;
+ case 1:
+ tmpl = InsetQuotes::SwedishQ;
+ break;
+ case 2:
+ tmpl = InsetQuotes::GermanQ;
+ break;
+ case 3:
+ tmpl = InsetQuotes::PolishQ;
+ break;
+ case 4:
+ tmpl = InsetQuotes::FrenchQ;
+ break;
+ case 5:
+ tmpl = InsetQuotes::DanishQ;
+ break;
}
+ params.quotes_language = tmpl;
} else if (token == "\\quotes_times") {
lex.nextToken();
switch (lex.getInteger()) {
int tmpret = lex.findToken(string_orientation);
if (tmpret == -1)
++tmpret;
- if (tmpret != LYX_LAYOUT_DEFAULT)
- params.orientation = static_cast<BufferParams::PAPER_ORIENTATION>(tmpret);
+ params.orientation =
+ static_cast<BufferParams::PAPER_ORIENTATION>(tmpret);
} else if (token == "\\paperwidth") {
lex.next();
params.paperwidth = lex.getString();
params.footskip = lex.getString();
} else if (token == "\\paperfontsize") {
lex.nextToken();
- params.fontsize = strip(lex.getString());
+ params.fontsize = rtrim(lex.getString());
} else if (token == "\\papercolumns") {
lex.nextToken();
params.columns = lex.getInteger();
}
} else if (token == "\\paperpagestyle") {
lex.nextToken();
- params.pagestyle = strip(lex.getString());
+ params.pagestyle = rtrim(lex.getString());
} else if (token == "\\bullet") {
lex.nextToken();
int const index = lex.getInteger();
params.tocdepth = lex.getInteger();
} else if (token == "\\spacing") {
lex.next();
- string const tmp = strip(lex.getString());
+ string const tmp = rtrim(lex.getString());
Spacing::Space tmp_space = Spacing::Default;
float tmp_val = 0.0;
if (tmp == "single") {
}
} else if (token == "\\paragraph_spacing") {
lex.next();
- string const tmp = strip(lex.getString());
+ string const tmp = rtrim(lex.getString());
if (tmp == "single") {
par->params().spacing(Spacing(Spacing::Single));
} else if (tmp == "onehalf") {
} else if (token == "\\align") {
int tmpret = lex.findToken(string_align);
if (tmpret == -1) ++tmpret;
- if (tmpret != LYX_LAYOUT_DEFAULT) { // tmpret != 99 ???
- int const tmpret2 = int(pow(2.0, tmpret));
- //lyxerr << "Tmpret2 = " << tmpret2 << endl;
- par->params().align(LyXAlignment(tmpret2));
- }
+ int const tmpret2 = int(pow(2.0, tmpret));
+ par->params().align(LyXAlignment(tmpret2));
} else if (token == "\\added_space_top") {
lex.nextToken();
VSpace value = VSpace(lex.getString());
for(string::const_iterator cit = str.begin();
cit != str.end(); ++cit) {
if (*cit == '\n') {
- if (autobreakrows && (par->size() || layout->keepempty)) {
+ if (autobreakrows && (!par->empty() || layout->keepempty)) {
par->breakParagraph(params, pos,
layout->isEnvironment());
par = par->next();
"Use LyX 0.10.x to read this!"));
return false;
} else if (file_format < 220) {
- //Alert::alert(_("Warning!"),
- // _("Old LyX file format found. "
- // "Running conversion script"));
- string command = "lyxconvert "
+ string const command = "lyx2lyx "
+ QuoteName(filename_);
cmd_ret const ret = RunCommand(command);
if (ret.first) {
}
}
- if (writeFile(fileName(), false)) {
- markLyxClean();
+ if (writeFile(fileName())) {
+ markClean();
removeAutosaveFile(fileName());
} else {
// Saving failed, so backup is not backup
}
-// Returns false if unsuccesful
-bool Buffer::writeFile(string const & fname, bool flag) const
+bool Buffer::writeFile(string const & fname) const
{
- // if flag is false writeFile will not create any GUI
- // warnings, only cerr.
- // Needed for autosave in background or panic save (Matthias 120496)
-
if (read_only && (fname == fileName())) {
- // Here we should come with a question if we should
- // perform the write anyway.
- if (flag)
- lyxerr << _("Error! Document is read-only: ")
- << fname << endl;
- else
- Alert::alert(_("Error! Document is read-only: "),
- fname);
return false;
}
FileInfo finfo(fname);
if (finfo.exist() && !finfo.writable()) {
- // Here we should come with a question if we should
- // try to do the save anyway. (i.e. do a chmod first)
- if (flag)
- lyxerr << _("Error! Cannot write file: ")
- << fname << endl;
- else
- Alert::err_alert(_("Error! Cannot write file: "),
- fname);
return false;
}
ofstream ofs(fname.c_str());
if (!ofs) {
- if (flag)
- lyxerr << _("Error! Cannot open file: ")
- << fname << endl;
- else
- Alert::err_alert(_("Error! Cannot open file: "),
- fname);
return false;
}
// this will write out all the paragraphs
// using recursive descent.
- paragraph->writeFile(this, ofs, params, depth);
+ paragraphs.begin()->writeFile(this, ofs, params, depth);
// Write marker that shows file is complete
ofs << "\n\\the_end" << endl;
void Buffer::writeFileAscii(ostream & ofs, int linelen)
{
- Paragraph * par = paragraph;
- while (par) {
- ofs << asciiParagraph(par, linelen, par->previous() == 0);
- par = par->next();
+ ParagraphList::iterator beg = paragraphs.begin();
+ ParagraphList::iterator end = paragraphs.end();
+ ParagraphList::iterator it = beg;
+ for (; it != end; ++it) {
+ ofs << asciiParagraph(&*it, linelen, it == beg);
}
ofs << "\n";
}
{
niceFile = nice; // this will be used by Insetincludes.
- tex_code_break_column = lyxrc.ascii_linelen;
-
// validate the buffer.
lyxerr[Debug::LATEX] << " Validating buffer..." << endl;
LaTeXFeatures features(params);
texrow.reset();
// The starting paragraph of the coming rows is the
// first paragraph of the document. (Asger)
- texrow.start(paragraph, 0);
+ texrow.start(&*(paragraphs.begin()), 0);
if (!only_body && nice) {
os << "%% " << lyx_docversion << " created this file. "
// usual is \batchmode and has a
// special input@path to allow the including of figures
// with either \input or \includegraphics (what figinsets do).
- // batchmode is not set if there is a tex_code_break_column.
- // In this case somebody is interested in the generated LaTeX,
- // so this is OK. input@path is set when the actual parameter
+ // input@path is set when the actual parameter
// original_path is set. This is done for usual tex-file, but not
// for nice-latex-file. (Matthias 250696)
if (!only_body) {
string strOptions(options.str().c_str());
if (!strOptions.empty()) {
- strOptions = strip(strOptions, ",");
+ strOptions = rtrim(strOptions, ",");
os << '[' << strOptions << ']';
}
texrow.newline();
}
- latexParagraphs(os, paragraph, 0, texrow);
+ latexParagraphs(os, &*(paragraphs.begin()), 0, texrow);
// add this just in case after all the paragraphs
os << endl;
// Just to be sure. (Asger)
texrow.newline();
- // tex_code_break_column's value is used to decide
- // if we are in batchmode or not (within mathed_write()
- // in math_write.C) so we must set it to a non-zero
- // value when we leave otherwise we save incorrect .lyx files.
- tex_code_break_column = lyxrc.ascii_linelen;
-
lyxerr[Debug::INFO] << "Finished making latex file." << endl;
lyxerr[Debug::INFO] << "Row count was " << texrow.rows()-1 << "." << endl;
<< " -->\n";
Paragraph::depth_type depth = 0; // paragraph depth
- Paragraph * par = paragraph;
+ Paragraph * par = &*(paragraphs.begin());
string item_name;
vector<string> environment_stack(5);
os << c;
++char_line_count;
} else {
- string sgml_string;
- if (par->sgmlConvertChar(c, sgml_string)
- && !style->free_spacing && !par->isFreeSpacing())
- {
+ bool ws;
+ string str;
+ boost::tie(ws, str) = sgml::escapeChar(c);
+ if (ws && !style->free_spacing && !par->isFreeSpacing()) {
// in freespacing mode, spaces are
// non-breaking characters
if (desc_on) {// if char is ' ' then...
os << c;
}
} else {
- os << sgml_string;
- char_line_count += sgml_string.length();
+ os << str;
+ char_line_count += str.length();
}
}
font_old = font;
return;
}
- Paragraph * par = paragraph;
+ Paragraph * par = &*(paragraphs.begin());
niceFile = nice; // this will be used by Insetincludes.
}
} else {
char c = par->getChar(i);
- string sgml_string;
- par->sgmlConvertChar(c, sgml_string);
+ bool ws;
+ string str;
+ boost::tie(ws, str) = sgml::escapeChar(c);
if (style->pass_thru) {
os << c;
} else if (style->free_spacing || par->isFreeSpacing() || c != ' ') {
- os << sgml_string;
+ os << str;
} else if (desc_on ==1) {
++char_line_count;
os << "\n</term><listitem><para>";
void Buffer::validate(LaTeXFeatures & features) const
{
- Paragraph * par = paragraph;
LyXTextClass const & tclass = params.getLyXTextClass();
// AMS Style is at document level
if (params.use_amsmath || tclass.provides(LyXTextClass::amsmath))
features.require("amsmath");
- while (par) {
- // We don't use "lyxerr.debug" because of speed. (Asger)
- if (lyxerr.debugging(Debug::LATEX))
- lyxerr << "Paragraph: " << par << endl;
-
- // Now just follow the list of paragraphs and run
- // validate on each of them.
- par->validate(features);
-
- // and then the next paragraph
- par = par->next();
- }
+ for_each(paragraphs.begin(), paragraphs.end(),
+ boost::bind(&Paragraph::validate, _1, boost::ref(features)));
// the bullet shapes are buffer level not paragraph level
// so they are tested here
}
-vector<string> const Buffer::getLabelList()
+vector<string> const Buffer::getLabelList() const
{
/// if this is a child document and the parent is already loaded
/// Use the parent's list instead [ale990407]
if (!params.parentname.empty()
&& bufferlist.exists(params.parentname)) {
- Buffer * tmp = bufferlist.getBuffer(params.parentname);
+ Buffer const * tmp = bufferlist.getBuffer(params.parentname);
if (tmp)
return tmp->getLabelList();
}
vector<string> label_list;
- for (inset_iterator it = inset_iterator_begin();
- it != inset_iterator_end(); ++it) {
+ for (inset_iterator it = inset_const_iterator_begin();
+ it != inset_const_iterator_end(); ++it) {
vector<string> const l = (*it)->getLabelList();
label_list.insert(label_list.end(), l.begin(), l.end());
}
}
vector<StringPair> keys;
- Paragraph * par = paragraph;
- while (par) {
- if (par->bibkey) {
- string const key = par->bibkey->getContents();
- string const opt = par->bibkey->getOptions();
- string const ref = par->asString(this, false);
+ ParagraphList::iterator pit = paragraphs.begin();
+ ParagraphList::iterator pend = paragraphs.end();
+ for (; pit != pend; ++pit) {
+ if (pit->bibkey) {
+ string const key = pit->bibkey->getContents();
+ string const opt = pit->bibkey->getOptions();
+ string const ref = pit->asString(this, false);
string const info = opt + "TheBibliographyRef" + ref;
keys.push_back(StringPair(key, info));
}
- par = par->next();
}
// Might be either using bibtex or a child has bibliography
{
// Split command string into command and argument
string cmd;
- string line = frontStrip(command);
- string const arg = strip(frontStrip(split(line, cmd, ' ')));
+ string line = ltrim(command);
+ string const arg = trim(split(line, cmd, ' '));
return dispatch(lyxaction.LookupFunc(cmd), arg, result);
}
void Buffer::resizeInsets(BufferView * bv)
{
/// then remove all LyXText in text-insets
- Paragraph * par = paragraph;
- for (; par; par = par->next()) {
- par->resizeInsetsLyXText(bv);
- }
+ for_each(paragraphs.begin(), paragraphs.end(),
+ boost::bind(&Paragraph::resizeInsetsLyXText, _1, bv));
}
}
+Counters & Buffer::counters() const
+{
+ return *ctrs.get();
+}
+
+
Buffer::inset_iterator::inset_iterator(Paragraph * paragraph, pos_type pos)
: par(paragraph)
{
- it = par->InsetIterator(pos);
- if (it == par->inset_iterator_end()) {
+ it = par->insetlist.insetIterator(pos);
+ if (it == par->insetlist.end()) {
par = par->next();
setParagraph();
}
void Buffer::inset_iterator::setParagraph()
{
while (par) {
- it = par->inset_iterator_begin();
- if (it != par->inset_iterator_end())
+ it = par->insetlist.begin();
+ if (it != par->insetlist.end())
return;
par = par->next();
}
Paragraph * Buffer::getParFromID(int id) const
{
- if (id < 0) return 0;
- Paragraph * par = paragraph;
- while (par) {
- if (par->id() == id) {
- return par;
+ if (id < 0)
+ return 0;
+
+ ParagraphList::iterator it = paragraphs.begin();
+ ParagraphList::iterator end = paragraphs.end();
+ for (; it != end; ++it) {
+ if (it->id() == id) {
+ return &*it;
}
- Paragraph * tmp = par->getParFromID(id);
+ Paragraph * tmp = it->getParFromID(id);
if (tmp) {
return tmp;
}
- par = par->next();
}
return 0;
}
ParIterator Buffer::par_iterator_begin()
{
- return ParIterator(paragraph);
+ return ParIterator(&*(paragraphs.begin()));
}