/**
* \file buffer.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Lars Gullik Bjønnes
*
* Full author contact details are available in file CREDITS
*/
#include
#include "buffer.h"
#include "bufferlist.h"
#include "LyXAction.h"
#include "lyxrc.h"
#include "lyxlex.h"
#include "tex-strings.h"
#include "layout.h"
#include "bufferview_funcs.h"
#include "lyxfont.h"
#include "version.h"
#include "LaTeX.h"
#include "Chktex.h"
#include "debug.h"
#include "LaTeXFeatures.h"
#include "lyxtext.h"
#include "gettext.h"
#include "language.h"
#include "exporter.h"
#include "Lsstream.h"
#include "format.h"
#include "BufferView.h"
#include "ParagraphParameters.h"
#include "iterators.h"
#include "lyxtextclasslist.h"
#include "sgml.h"
#include "paragraph_funcs.h"
#include "author.h"
#include "frontends/LyXView.h"
#include "mathed/formulamacro.h"
#include "mathed/formula.h"
#include "insets/inseterror.h"
#include "insets/insetbibitem.h"
#include "insets/insetbibtex.h"
#include "insets/insetinclude.h"
#include "insets/insettext.h"
#include "frontends/Dialogs.h"
#include "frontends/Alert.h"
#include "graphics/Previews.h"
#include "support/textutils.h"
#include "support/filetools.h"
#include "support/path.h"
#include "support/os.h"
#include "support/lyxlib.h"
#include "support/FileInfo.h"
#include "support/lyxmanip.h"
#include "support/lyxtime.h"
#include
#include
#include "BoostFormat.h"
#include
#include
#include
";
}
sgml::openTag(ofs, depth, false, style->latexname());
break;
case LATEX_COMMAND:
if (depth!= 0)
sgmlError(par, 0,
_("Error: Wrong depth for LatexType Command.\n"));
if (!environment_stack[depth].empty()) {
sgml::closeTag(ofs, depth, false, environment_stack[depth]);
ofs << "";
}
environment_stack[depth].erase();
sgml::openTag(ofs, depth, false, style->latexname());
break;
case LATEX_ENVIRONMENT:
case LATEX_ITEM_ENVIRONMENT:
case LATEX_BIB_ENVIRONMENT:
{
string const & latexname = style->latexname();
if (depth == par->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();
environment_stack[depth].erase();
}
if (environment_stack[depth] != latexname) {
if (depth == 0) {
sgml::openTag(ofs, depth, false, "p");
}
sgml::openTag(ofs, depth, false, latexname);
if (environment_stack.size() == depth + 1)
environment_stack.push_back("!-- --");
environment_stack[depth] = latexname;
}
if (style->latexparam() == "CDATA")
ofs << "latextype == LATEX_ENVIRONMENT) break;
if (style->labeltype == LABEL_MANUAL)
item_name = "tag";
else
item_name = "item";
sgml::openTag(ofs, depth + 1, false, item_name);
}
break;
default:
sgml::openTag(ofs, depth, false, style->latexname());
break;
}
simpleLinuxDocOnePar(ofs, par, depth);
par = par->next();
ofs << "\n";
// write closing SGML tags
switch (style->latextype) {
case LATEX_COMMAND:
break;
case LATEX_ENVIRONMENT:
case LATEX_ITEM_ENVIRONMENT:
case LATEX_BIB_ENVIRONMENT:
if (style->latexparam() == "CDATA")
ofs << "]]>";
break;
default:
sgml::closeTag(ofs, depth, false, style->latexname());
break;
}
}
// Close open tags
for (int i = depth; i >= 0; --i)
sgml::closeTag(ofs, depth, false, environment_stack[i]);
if (!body_only) {
ofs << "\n\n";
sgml::closeTag(ofs, 0, false, top_element);
}
ofs.close();
// How to check for successful close
// we want this to be true outside previews (for insetexternal)
niceFile = true;
}
// checks, if newcol chars should be put into this line
// writes newline, if necessary.
namespace {
void sgmlLineBreak(ostream & os, string::size_type & colcount,
string::size_type newcol)
{
colcount += newcol;
if (colcount > lyxrc.ascii_linelen) {
os << "\n";
colcount = newcol; // assume write after this call
}
}
enum PAR_TAG {
NONE=0,
TT = 1,
SF = 2,
BF = 4,
IT = 8,
SL = 16,
EM = 32
};
string tag_name(PAR_TAG const & pt) {
switch (pt) {
case NONE: return "!-- --";
case TT: return "tt";
case SF: return "sf";
case BF: return "bf";
case IT: return "it";
case SL: return "sl";
case EM: return "em";
}
return "";
}
inline
void operator|=(PAR_TAG & p1, PAR_TAG const & p2)
{
p1 = static_cast(p1 | p2);
}
inline
void reset(PAR_TAG & p1, PAR_TAG const & p2)
{
p1 = static_cast(p1 & ~p2);
}
} // anon
// Handle internal paragraph parsing -- layout already processed.
void Buffer::simpleLinuxDocOnePar(ostream & os,
Paragraph * par,
Paragraph::depth_type /*depth*/)
{
LyXLayout_ptr const & style = par->layout();
string::size_type char_line_count = 5; // Heuristic choice ;-)
// gets paragraph main font
LyXFont font_old;
bool desc_on;
if (style->labeltype == LABEL_MANUAL) {
font_old = style->labelfont;
desc_on = true;
} else {
font_old = style->font;
desc_on = false;
}
LyXFont::FONT_FAMILY family_type = LyXFont::ROMAN_FAMILY;
LyXFont::FONT_SERIES series_type = LyXFont::MEDIUM_SERIES;
LyXFont::FONT_SHAPE shape_type = LyXFont::UP_SHAPE;
bool is_em = false;
stack tag_state;
// parsing main loop
for (pos_type i = 0; i < par->size(); ++i) {
PAR_TAG tag_close = NONE;
list < PAR_TAG > tag_open;
LyXFont const font = par->getFont(params, i);
if (font_old.family() != font.family()) {
switch (family_type) {
case LyXFont::SANS_FAMILY:
tag_close |= SF;
break;
case LyXFont::TYPEWRITER_FAMILY:
tag_close |= TT;
break;
default:
break;
}
family_type = font.family();
switch (family_type) {
case LyXFont::SANS_FAMILY:
tag_open.push_back(SF);
break;
case LyXFont::TYPEWRITER_FAMILY:
tag_open.push_back(TT);
break;
default:
break;
}
}
if (font_old.series() != font.series()) {
switch (series_type) {
case LyXFont::BOLD_SERIES:
tag_close |= BF;
break;
default:
break;
}
series_type = font.series();
switch (series_type) {
case LyXFont::BOLD_SERIES:
tag_open.push_back(BF);
break;
default:
break;
}
}
if (font_old.shape() != font.shape()) {
switch (shape_type) {
case LyXFont::ITALIC_SHAPE:
tag_close |= IT;
break;
case LyXFont::SLANTED_SHAPE:
tag_close |= SL;
break;
default:
break;
}
shape_type = font.shape();
switch (shape_type) {
case LyXFont::ITALIC_SHAPE:
tag_open.push_back(IT);
break;
case LyXFont::SLANTED_SHAPE:
tag_open.push_back(SL);
break;
default:
break;
}
}
// handle tag
if (font_old.emph() != font.emph()) {
if (font.emph() == LyXFont::ON) {
tag_open.push_back(EM);
is_em = true;
}
else if (is_em) {
tag_close |= EM;
is_em = false;
}
}
list < PAR_TAG > temp;
while (!tag_state.empty() && tag_close) {
PAR_TAG k = tag_state.top();
tag_state.pop();
os << "" << tag_name(k) << '>';
if (tag_close & k)
reset(tag_close,k);
else
temp.push_back(k);
}
for(list< PAR_TAG >::const_iterator j = temp.begin();
j != temp.end(); ++j) {
tag_state.push(*j);
os << '<' << tag_name(*j) << '>';
}
for(list< PAR_TAG >::const_iterator j = tag_open.begin();
j != tag_open.end(); ++j) {
tag_state.push(*j);
os << '<' << tag_name(*j) << '>';
}
char c = par->getChar(i);
if (c == Paragraph::META_INSET) {
Inset * inset = par->getInset(i);
inset->linuxdoc(this, os);
font_old = font;
continue;
}
if (style->latexparam() == "CDATA") {
// "TeX"-Mode on == > SGML-Mode on.
if (c != '\0')
os << c;
++char_line_count;
} else {
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...
++char_line_count;
sgmlLineBreak(os, char_line_count, 6);
os << "";
desc_on = false;
} else {
sgmlLineBreak(os, char_line_count, 1);
os << c;
}
} else {
os << str;
char_line_count += str.length();
}
}
font_old = font;
}
while (!tag_state.empty()) {
os << "" << tag_name(tag_state.top()) << '>';
tag_state.pop();
}
// resets description flag correctly
if (desc_on) {
// not closed...
sgmlLineBreak(os, char_line_count, 6);
os << "";
}
}
// 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::makeDocBookFile(string const & fname, bool nice, bool only_body)
{
ofstream ofs(fname.c_str());
if (!ofs) {
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;
return;
}
Paragraph * par = &*(paragraphs.begin());
niceFile = nice; // this will be used by Insetincludes.
LaTeXFeatures features(params);
validate(features);
texrow.reset();
LyXTextClass const & tclass = params.getLyXTextClass();
string top_element = tclass.latexname();
if (!only_body) {
ofs << "\n\n";
}
string top = top_element;
top += " lang=\"";
top += params.language->code();
top += '"';
if (!params.options.empty()) {
top += ' ';
top += params.options;
}
sgml::openTag(ofs, 0, false, top);
ofs << "\n";
vector environment_stack(10);
vector environment_inner(10);
vector command_stack(10);
bool command_flag = false;
Paragraph::depth_type command_depth = 0;
Paragraph::depth_type command_base = 0;
Paragraph::depth_type cmd_depth = 0;
Paragraph::depth_type depth = 0; // paragraph depth
string item_name;
string command_name;
while (par) {
string sgmlparam;
string c_depth;
string c_params;
int desc_on = 0; // description mode
LyXLayout_ptr const & style = par->layout();
// environment tag closing
for (; depth > par->params().depth(); --depth) {
if (environment_inner[depth] != "!-- --") {
item_name = "listitem";
sgml::closeTag(ofs, command_depth + depth, false, item_name);
if (environment_inner[depth] == "varlistentry")
sgml::closeTag(ofs, depth+command_depth, false, environment_inner[depth]);
}
sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]);
environment_stack[depth].erase();
environment_inner[depth].erase();
}
if (depth == par->params().depth()
&& environment_stack[depth] != style->latexname()
&& !environment_stack[depth].empty()) {
if (environment_inner[depth] != "!-- --") {
item_name= "listitem";
sgml::closeTag(ofs, command_depth+depth, false, item_name);
if (environment_inner[depth] == "varlistentry")
sgml::closeTag(ofs, depth + command_depth, false, environment_inner[depth]);
}
sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]);
environment_stack[depth].erase();
environment_inner[depth].erase();
}
// Write opening SGML tags.
switch (style->latextype) {
case LATEX_PARAGRAPH:
sgml::openTag(ofs, depth + command_depth,
false, style->latexname());
break;
case LATEX_COMMAND:
if (depth != 0)
sgmlError(par, 0,
_("Error: Wrong depth for LatexType Command.\n"));
command_name = style->latexname();
sgmlparam = style->latexparam();
c_params = split(sgmlparam, c_depth,'|');
cmd_depth = lyx::atoi(c_depth);
if (command_flag) {
if (cmd_depth < command_base) {
for (Paragraph::depth_type j = command_depth;
j >= command_base; --j) {
sgml::closeTag(ofs, j, false, command_stack[j]);
ofs << endl;
}
command_depth = command_base = cmd_depth;
} else if (cmd_depth <= command_depth) {
for (int j = command_depth;
j >= int(cmd_depth); --j) {
sgml::closeTag(ofs, j, false, command_stack[j]);
ofs << endl;
}
command_depth = cmd_depth;
} else
command_depth = cmd_depth;
} else {
command_depth = command_base = cmd_depth;
command_flag = true;
}
if (command_stack.size() == command_depth + 1)
command_stack.push_back(string());
command_stack[command_depth] = command_name;
// treat label as a special case for
// more WYSIWYM handling.
// This is a hack while paragraphs can't have
// attributes, like id in this case.
if (par->isInset(0)) {
Inset * inset = par->getInset(0);
Inset::Code lyx_code = inset->lyxCode();
if (lyx_code == Inset::LABEL_CODE) {
command_name += " id=\"";
command_name += (static_cast(inset))->getContents();
command_name += '"';
desc_on = 3;
}
}
sgml::openTag(ofs, depth + command_depth, false, command_name);
item_name = c_params.empty() ? "title" : c_params;
sgml::openTag(ofs, depth + 1 + command_depth, false, item_name);
break;
case LATEX_ENVIRONMENT:
case LATEX_ITEM_ENVIRONMENT:
if (depth < par->params().depth()) {
depth = par->params().depth();
environment_stack[depth].erase();
}
if (environment_stack[depth] != style->latexname()) {
if (environment_stack.size() == depth + 1) {
environment_stack.push_back("!-- --");
environment_inner.push_back("!-- --");
}
environment_stack[depth] = style->latexname();
environment_inner[depth] = "!-- --";
sgml::openTag(ofs, depth + command_depth, false, environment_stack[depth]);
} else {
if (environment_inner[depth] != "!-- --") {
item_name= "listitem";
sgml::closeTag(ofs, command_depth + depth, false, item_name);
if (environment_inner[depth] == "varlistentry")
sgml::closeTag(ofs, depth + command_depth, false, environment_inner[depth]);
}
}
if (style->latextype == LATEX_ENVIRONMENT) {
if (!style->latexparam().empty()) {
if (style->latexparam() == "CDATA")
ofs << "latexparam());
}
break;
}
desc_on = (style->labeltype == LABEL_MANUAL);
environment_inner[depth] = desc_on ? "varlistentry" : "listitem";
sgml::openTag(ofs, depth + 1 + command_depth,
false, environment_inner[depth]);
item_name = desc_on ? "term" : "para";
sgml::openTag(ofs, depth + 1 + command_depth,
false, item_name);
break;
default:
sgml::openTag(ofs, depth + command_depth,
false, style->latexname());
break;
}
simpleDocBookOnePar(ofs, par, desc_on,
depth + 1 + command_depth);
par = par->next();
string end_tag;
// write closing SGML tags
switch (style->latextype) {
case LATEX_COMMAND:
end_tag = c_params.empty() ? "title" : c_params;
sgml::closeTag(ofs, depth + command_depth,
false, end_tag);
break;
case LATEX_ENVIRONMENT:
if (!style->latexparam().empty()) {
if (style->latexparam() == "CDATA")
ofs << "]]>";
else
sgml::closeTag(ofs, depth + command_depth, false, style->latexparam());
}
break;
case LATEX_ITEM_ENVIRONMENT:
if (desc_on == 1) break;
end_tag = "para";
sgml::closeTag(ofs, depth + 1 + command_depth, false, end_tag);
break;
case LATEX_PARAGRAPH:
sgml::closeTag(ofs, depth + command_depth, false, style->latexname());
break;
default:
sgml::closeTag(ofs, depth + command_depth, false, style->latexname());
break;
}
}
// Close open tags
for (int d = depth; d >= 0; --d) {
if (!environment_stack[depth].empty()) {
if (environment_inner[depth] != "!-- --") {
item_name = "listitem";
sgml::closeTag(ofs, command_depth + depth, false, item_name);
if (environment_inner[depth] == "varlistentry")
sgml::closeTag(ofs, depth + command_depth, false, environment_inner[depth]);
}
sgml::closeTag(ofs, depth + command_depth, false, environment_stack[depth]);
}
}
for (int j = command_depth; j >= 0 ; --j)
if (!command_stack[j].empty()) {
sgml::closeTag(ofs, j, false, command_stack[j]);
ofs << endl;
}
ofs << "\n\n";
sgml::closeTag(ofs, 0, false, top_element);
ofs.close();
// How to check for successful close
// we want this to be true outside previews (for insetexternal)
niceFile = true;
}
void Buffer::simpleDocBookOnePar(ostream & os,
Paragraph * par, int & desc_on,
Paragraph::depth_type depth) const
{
bool emph_flag = false;
LyXLayout_ptr const & style = par->layout();
LyXFont font_old = (style->labeltype == LABEL_MANUAL ? style->labelfont : style->font);
int char_line_count = depth;
//if (!style.free_spacing)
// os << string(depth,' ');
// parsing main loop
for (pos_type i = 0; i < par->size(); ++i) {
LyXFont font = par->getFont(params, i);
// handle tag
if (font_old.emph() != font.emph()) {
if (font.emph() == LyXFont::ON) {
if (style->latexparam() == "CDATA")
os << "]]>";
os << "";
if (style->latexparam() == "CDATA")
os << "latexparam() == "CDATA")
os << "]]>";
os << "";
if (style->latexparam() == "CDATA")
os << "isInset(i)) {
Inset * inset = par->getInset(i);
// don't print the inset in position 0 if desc_on == 3 (label)
if (i || desc_on != 3) {
if (style->latexparam() == "CDATA")
os << "]]>";
inset->docbook(this, os, false);
if (style->latexparam() == "CDATA")
os << "getChar(i);
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 << str;
} else if (desc_on ==1) {
++char_line_count;
os << "\n";
desc_on = 2;
} else {
os << ' ';
}
}
font_old = font;
}
if (emph_flag) {
if (style->latexparam() == "CDATA")
os << "]]>";
os << "";
if (style->latexparam() == "CDATA")
os << " not closed...
os << "\n ";
}
if (style->free_spacing)
os << '\n';
}
// chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
// Other flags: -wall -v0 -x
int Buffer::runChktex()
{
if (!users->text) return 0;
users->owner()->busy(true);
// get LaTeX-Filename
string const name = getLatexName();
string path = filePath();
string const org_path = path;
if (lyxrc.use_tempdir || !IsDirWriteable(path)) {
path = tmppath;
}
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);
TeXErrors terr;
Chktex chktex(lyxrc.chktex_command, name, filePath());
int res = chktex.run(terr); // run chktex
if (res == -1) {
Alert::error(_("chktex failure"),
_("Could not run chktex successfully."));
} else if (res > 0) {
// Insert all errors as errors boxes
users->insertErrors(terr);
}
// 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::validate(LaTeXFeatures & features) const
{
LyXTextClass const & tclass = params.getLyXTextClass();
if (params.tracking_changes) {
features.require("dvipost");
features.require("color");
}
// AMS Style is at document level
if (params.use_amsmath == BufferParams::AMS_ON
|| tclass.provides(LyXTextClass::amsmath))
features.require("amsmath");
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
for (int i = 0; i < 4; ++i) {
if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
int const font = params.user_defined_bullets[i].getFont();
if (font == 0) {
int const c = params
.user_defined_bullets[i]
.getCharacter();
if (c == 16
|| c == 17
|| c == 25
|| c == 26
|| c == 31) {
features.require("latexsym");
}
} else if (font == 1) {
features.require("amssymb");
} else if ((font >= 2 && font <= 5)) {
features.require("pifont");
}
}
}
if (lyxerr.debugging(Debug::LATEX)) {
features.showStruct();
}
}
vector 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 const * tmp = bufferlist.getBuffer(params.parentname);
if (tmp)
return tmp->getLabelList();
}
vector label_list;
for (inset_iterator it = inset_const_iterator_begin();
it != inset_const_iterator_end(); ++it) {
vector const l = it->getLabelList();
label_list.insert(label_list.end(), l.begin(), l.end());
}
return label_list;
}
// This is also a buffer property (ale)
void Buffer::fillWithBibKeys(vector > & keys) const
{
/// if this is a child document and the parent is already loaded
/// use the parent's list instead [ale990412]
if (!params.parentname.empty() && bufferlist.exists(params.parentname)) {
Buffer const * tmp = bufferlist.getBuffer(params.parentname);
if (tmp) {
tmp->fillWithBibKeys(keys);
return;
}
}
for (inset_iterator it = inset_const_iterator_begin();
it != inset_const_iterator_end(); ++it) {
if (it->lyxCode() == Inset::BIBTEX_CODE)
static_cast(*it).fillWithBibKeys(this, keys);
else if (it->lyxCode() == Inset::INCLUDE_CODE)
static_cast(*it).fillWithBibKeys(keys);
else if (it->lyxCode() == Inset::BIBITEM_CODE) {
InsetBibitem & bib = static_cast(*it);
string const key = bib.getContents();
string const opt = bib.getOptions();
string const ref; // = pit->asString(this, false);
string const info = opt + "TheBibliographyRef" + ref;
keys.push_back(pair(key, info));
}
}
}
bool Buffer::isDepClean(string const & name) const
{
DepClean::const_iterator it = dep_clean_.find(name);
if (it == dep_clean_.end())
return true;
return it->second;
}
void Buffer::markDepClean(string const & name)
{
dep_clean_[name] = true;
}
bool Buffer::dispatch(string const & command, bool * result)
{
// Split command string into command and argument
string cmd;
string line = ltrim(command);
string const arg = trim(split(line, cmd, ' '));
return dispatch(lyxaction.LookupFunc(cmd), arg, result);
}
bool Buffer::dispatch(int action, string const & argument, bool * result)
{
bool dispatched = true;
switch (action) {
case LFUN_EXPORT: {
bool const tmp = Exporter::Export(this, argument, false);
if (result)
*result = tmp;
break;
}
default:
dispatched = false;
}
return dispatched;
}
void Buffer::resizeInsets(BufferView * bv)
{
/// then remove all LyXText in text-insets
for_each(paragraphs.begin(), paragraphs.end(),
boost::bind(&Paragraph::resizeInsetsLyXText, _1, bv));
}
void Buffer::redraw()
{
#warning repaint needed here, or do you mean update() ?
users->repaint();
users->fitCursor();
}
void Buffer::changeLanguage(Language const * from, Language const * to)
{
ParIterator end = par_iterator_end();
for (ParIterator it = par_iterator_begin(); it != end; ++it)
(*it)->changeLanguage(params, from, to);
}
bool Buffer::isMultiLingual()
{
ParIterator end = par_iterator_end();
for (ParIterator it = par_iterator_begin(); it != end; ++it)
if ((*it)->isMultiLingual(params))
return true;
return false;
}
void Buffer::inset_iterator::setParagraph()
{
while (pit != pend) {
it = pit->insetlist.begin();
if (it != pit->insetlist.end())
return;
++pit;
}
}
Inset * Buffer::getInsetFromID(int id_arg) const
{
for (inset_iterator it = inset_const_iterator_begin();
it != inset_const_iterator_end(); ++it)
{
if (it->id() == id_arg)
return &(*it);
Inset * in = it->getInsetFromID(id_arg);
if (in)
return in;
}
return 0;
}
Paragraph * Buffer::getParFromID(int id) const
{
if (id < 0)
return 0;
// why should we allow < 0 ??
//lyx::Assert(id >= 0);
ParConstIterator it(par_iterator_begin());
ParConstIterator end(par_iterator_end());
for (; it != end; ++it) {
// go on then, show me how to remove
// the cast
if ((*it)->id() == id) {
return const_cast(*it);
}
}
return 0;
}
ParIterator Buffer::par_iterator_begin()
{
return ParIterator(&*(paragraphs.begin()));
}
ParIterator Buffer::par_iterator_end()
{
return ParIterator();
}
ParConstIterator Buffer::par_iterator_begin() const
{
return ParConstIterator(&*(paragraphs.begin()));
}
ParConstIterator Buffer::par_iterator_end() const
{
return ParConstIterator();
}
void Buffer::addUser(BufferView * u)
{
users = u;
}
void Buffer::delUser(BufferView *)
{
users = 0;
}
Language const * Buffer::getLanguage() const
{
return params.language;
}
bool Buffer::isClean() const
{
return lyx_clean;
}
bool Buffer::isBakClean() const
{
return bak_clean;
}
void Buffer::markClean() const
{
if (!lyx_clean) {
lyx_clean = true;
updateTitles();
}
// if the .lyx file has been saved, we don't need an
// autosave
bak_clean = true;
}
void Buffer::markBakClean()
{
bak_clean = true;
}
void Buffer::setUnnamed(bool flag)
{
unnamed = flag;
}
bool Buffer::isUnnamed()
{
return unnamed;
}
void Buffer::markDirty()
{
if (lyx_clean) {
lyx_clean = false;
updateTitles();
}
bak_clean = false;
DepClean::iterator it = dep_clean_.begin();
DepClean::const_iterator const end = dep_clean_.end();
for (; it != end; ++it) {
it->second = false;
}
}
string const & Buffer::fileName() const
{
return filename_;
}
string const & Buffer::filePath() const
{
return filepath_;
}
bool Buffer::isReadonly() const
{
return read_only;
}
BufferView * Buffer::getUser() const
{
return users;
}
void Buffer::setParentName(string const & name)
{
params.parentname = name;
}
Buffer::inset_iterator::inset_iterator()
: pit(0), pend(0)
{}
Buffer::inset_iterator::inset_iterator(base_type p, base_type e)
: pit(p), pend(e)
{
setParagraph();
}
Buffer::inset_iterator & Buffer::inset_iterator::operator++()
{
if (pit != pend) {
++it;
if (it == pit->insetlist.end()) {
++pit;
setParagraph();
}
}
return *this;
}
Buffer::inset_iterator Buffer::inset_iterator::operator++(int)
{
inset_iterator tmp = *this;
++*this;
return tmp;
}
Buffer::inset_iterator::reference Buffer::inset_iterator::operator*()
{
return *it.getInset();
}
Buffer::inset_iterator::pointer Buffer::inset_iterator::operator->()
{
return it.getInset();
}
Paragraph * Buffer::inset_iterator::getPar()
{
return &(*pit);
}
lyx::pos_type Buffer::inset_iterator::getPos() const
{
return it.getPos();
}
bool operator==(Buffer::inset_iterator const & iter1,
Buffer::inset_iterator const & iter2)
{
return iter1.pit == iter2.pit
&& (iter1.pit == iter1.pend || iter1.it == iter2.it);
}
bool operator!=(Buffer::inset_iterator const & iter1,
Buffer::inset_iterator const & iter2)
{
return !(iter1 == iter2);
}