*
* \author Asger Alstrup
* \author Lars Gullik Bjønnes
+ * \author Richard Heck (XHTML output)
* \author Jean-Marc Lasgouttes
* \author Angus Leeming
* \author John Levon
OutputParams const & runparams);
///
- void validate(LaTeXFeatures & features,
- Layout const & layout) const;
+ void validate(LaTeXFeatures & features) const;
/// Checks if the paragraph contains only text and no inset or font change.
bool onlyText(Buffer const & buf, Font const & outerfont,
FontList fontlist_;
///
- unsigned int id_;
- ///
- static unsigned int paragraph_id;
+ int id_;
+
///
ParagraphParameters params_;
///
TextContainer text_;
- typedef std::set<docstring> Words;
+ typedef set<docstring> Words;
///
- Words words_;
+ map<Language, Words> words_;
///
Layout const * layout_;
};
-// Initialization of the counter for the paragraph id's,
-unsigned int Paragraph::Private::paragraph_id = 0;
-
namespace {
struct special_phrase {
Paragraph::Private::Private(Paragraph * owner, Layout const & layout)
- : owner_(owner), inset_owner_(0), begin_of_body_(0), layout_(&layout)
+ : owner_(owner), inset_owner_(0), id_(-1), begin_of_body_(0), layout_(&layout)
{
- id_ = paragraph_id++;
text_.reserve(100);
}
Paragraph::Private::Private(Private const & p, Paragraph * owner)
: owner_(owner), inset_owner_(p.inset_owner_), fontlist_(p.fontlist_),
- params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_),
+ id_(p.id_), params_(p.params_), changes_(p.changes_), insetlist_(p.insetlist_),
begin_of_body_(p.begin_of_body_), text_(p.text_), words_(p.words_),
layout_(p.layout_)
{
- id_ = paragraph_id++;
}
begin_of_body_(p.begin_of_body_), words_(p.words_),
layout_(p.layout_)
{
- id_ = paragraph_id++;
if (beg >= pos_type(p.text_.size()))
return;
text_ = p.text_.substr(beg, end - beg);
if (inset->canTrackChanges()) {
column += Changes::latexMarkChange(os, bparams, running_change,
- Change(Change::UNCHANGED));
+ Change(Change::UNCHANGED), runparams);
running_change = Change(Change::UNCHANGED);
}
}
-void Paragraph::Private::validate(LaTeXFeatures & features,
- Layout const & layout) const
+void Paragraph::Private::validate(LaTeXFeatures & features) const
{
+ if (layout_->inpreamble && inset_owner_) {
+ Buffer const & buf = inset_owner_->buffer();
+ BufferParams const & bp = buf.params();
+ Font f;
+ TexRow tr;
+ odocstringstream ods;
+ owner_->latex(bp, f, ods, tr, features.runparams());
+ docstring d = ods.str();
+ if (!d.empty())
+ features.addPreambleSnippet(to_utf8(d));
+ }
+
// check the params.
if (!params_.spacing().isDefault())
features.require("setspace");
// then the layouts
- features.useLayout(layout.name());
+ features.useLayout(layout_->name());
// then the fonts
fontlist_.validate(features);
for (; icit != iend; ++icit) {
if (icit->inset) {
icit->inset->validate(features);
- if (layout.needprotect &&
+ if (layout_->needprotect &&
icit->inset->lyxCode() == FOOT_CODE)
features.require("NeedLyXFootnoteCode");
}
}
+namespace {
+
+// this shall be called just before every "os << ..." action.
+void flushString(ostream & os, docstring & s)
+{
+ os << to_utf8(s);
+ s.erase();
+}
+
+}
+
+
void Paragraph::write(ostream & os, BufferParams const & bparams,
depth_type & dth) const
{
Change running_change = Change(Change::UNCHANGED);
+ // this string is used as a buffer to avoid repetitive calls
+ // to to_utf8(), which turn out to be expensive (JMarc)
+ docstring write_buffer;
+
int column = 0;
for (pos_type i = 0; i <= size(); ++i) {
Change const change = lookupChange(i);
+ if (change != running_change)
+ flushString(os, write_buffer);
Changes::lyxMarkChange(os, bparams, column, running_change, change);
running_change = change;
Font font2 = getFontSettings(bparams, i);
font2.setMisspelled(false);
if (font2 != font1) {
+ flushString(os, write_buffer);
font2.lyxWriteChanges(font1, os);
column = 0;
font1 = font2;
switch (c) {
case META_INSET:
if (Inset const * inset = getInset(i)) {
+ flushString(os, write_buffer);
if (inset->directWrite()) {
// international char, let it write
// code directly so it's shorter in
}
break;
case '\\':
+ flushString(os, write_buffer);
os << "\n\\backslash\n";
column = 0;
break;
case '.':
+ flushString(os, write_buffer);
if (i + 1 < size() && d->text_[i + 1] == ' ') {
os << ".\n";
column = 0;
default:
if ((column > 70 && c == ' ')
|| column > 79) {
+ flushString(os, write_buffer);
os << '\n';
column = 0;
}
// this check is to amend a bug. LyX sometimes
// inserts '\0' this could cause problems.
if (c != '\0')
- os << to_utf8(docstring(1, c));
+ write_buffer.push_back(c);
else
LYXERR0("NUL char in structure.");
++column;
}
}
+ flushString(os, write_buffer);
os << "\n\\end_layout\n";
}
void Paragraph::validate(LaTeXFeatures & features) const
{
- d->validate(features, *d->layout_);
+ d->validate(features);
}
{
LYXERR(Debug::LATEX, "Paragraph::latex... " << this);
+ if (layout().inpreamble)
+ return true;
+
bool return_value = false;
bool const allowcust = allowParagraphCustomization();
running_font = basefont;
column += Changes::latexMarkChange(os, bparams,
- runningChange, Change(Change::UNCHANGED));
+ runningChange, Change(Change::UNCHANGED),
+ runparams);
runningChange = Change(Change::UNCHANGED);
os << "] ";
basefont = getLayoutFont(bparams, outerfont);
running_font = basefont;
- column += Changes::latexMarkChange(os, bparams, runningChange, change);
+ column += Changes::latexMarkChange(os, bparams, runningChange,
+ change, runparams);
runningChange = change;
}
#endif
}
- column += Changes::latexMarkChange(os, bparams, runningChange, Change(Change::UNCHANGED));
+ column += Changes::latexMarkChange(os, bparams, runningChange,
+ Change(Change::UNCHANGED), runparams);
// Needed if there is an optional argument but no contents.
if (body_pos > 0 && body_pos == size()) {
return_value = false;
}
- if (allowcust && d->endTeXParParams(bparams, os, texrow, runparams))
+ if (allowcust && d->endTeXParParams(bparams, os, texrow, runparams)
+ && runparams.encoding != prev_encoding) {
runparams.encoding = prev_encoding;
+ if (!bparams.useXetex)
+ os << setEncoding(prev_encoding->iconvName());
+ }
LYXERR(Debug::LATEX, "Paragraph::latex... done " << this);
return return_value;
}
-pos_type Paragraph::firstWordLyXHTML(odocstream & os, OutputParams const & runparams)
+pos_type Paragraph::firstWordLyXHTML(XHTMLStream & xs, OutputParams const & runparams)
const
{
pos_type i;
for (i = 0; i < size(); ++i) {
if (Inset const * inset = getInset(i)) {
- inset->xhtml(os, runparams);
+ inset->xhtml(xs, runparams);
} else {
char_type c = d->text_[i];
if (c == ' ')
break;
- os << html::escapeChar(c);
+ xs << c;
}
}
return i;
docstring Paragraph::simpleLyXHTMLOnePar(Buffer const & buf,
- odocstream & os,
+ XHTMLStream & xs,
OutputParams const & runparams,
Font const & outerfont,
+ bool fortoc,
pos_type initial) const
{
docstring retval;
- // FIXME We really need to manage the tag nesting here.
- // Probably in the same sort of way as in output_xhtml.
bool emph_flag = false;
bool bold_flag = false;
- std::string closing_tag;
+ string closing_tag;
Layout const & style = *d->layout_;
+
+ if (!fortoc) {
+ // generate a magic label for this paragraph
+ string const attr = "id='" + magicLabel() + "'";
+ xs << CompTag("a", attr);
+ }
+
FontInfo font_old =
style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
- //if (style.pass_thru && !d->onlyText(buf, outerfont, initial))
- // os << "]]>";
-
// parsing main loop
for (pos_type i = initial; i < size(); ++i) {
Font font = getFont(buf.params(), i, outerfont);
// emphasis
if (font_old.emph() != font.fontInfo().emph()) {
if (font.fontInfo().emph() == FONT_ON) {
- os << "<em>";
+ xs << StartTag("em");
emph_flag = true;
} else if (emph_flag && i != initial) {
- os << "</em>";
+ xs << EndTag("em");
emph_flag = false;
}
}
// bold
if (font_old.series() != font.fontInfo().series()) {
if (font.fontInfo().series() == BOLD_SERIES) {
- os << "<strong>";
+ xs << StartTag("strong");
bold_flag = true;
} else if (bold_flag && i != initial) {
- os << "</strong>";
+ xs << EndTag("strong");
bold_flag = false;
}
}
- // FIXME Other such tags?
-
- if (Inset const * inset = getInset(i)) {
- retval += inset->xhtml(os, runparams);
+ // FIXME XHTML
+ // Other such tags? What about the other text ranges?
+
+ Inset const * inset = getInset(i);
+ if (inset) {
+ InsetCommand const * ic = inset->asInsetCommand();
+ InsetLayout const & il = inset->getLayout();
+ if (!fortoc || il.isInToc() || (ic && ic->isInToc())) {
+ OutputParams np = runparams;
+ if (!il.htmlisblock())
+ np.html_in_par = true;
+ retval += inset->xhtml(xs, np);
+ }
} else {
char_type c = d->text_[i];
if (style.pass_thru)
- os.put(c);
+ xs << c;
else if (c == '-') {
docstring str;
int j = i + 1;
}
else
str += c;
- os << str;
+ // We don't want to escape the entities. Note that
+ // it is safe to do this, since str can otherwise
+ // only be "-". E.g., it can't be "<".
+ xs << XHTMLStream::NextRaw() << str;
} else
- os << html::escapeChar(c);
+ xs << c;
}
font_old = font.fontInfo();
}
- // FIXME This could be out of order. See above.
- if (emph_flag)
- os << "</em>";
- if (bold_flag)
- os << "</strong>";
-
+ xs.closeFontTags();
return retval;
}
}
+void Paragraph::setId(int id)
+{
+ d->id_ = id;
+}
+
+
Layout const & Paragraph::layout() const
{
return *d->layout_;
// There was no inset at the beginning, so we need to create one with
// the key and label of the one we erased.
InsetBibitem * inset =
- new InsetBibitem(buffer, InsetCommandParams(BIBITEM_CODE));
+ new InsetBibitem(const_cast<Buffer *>(&buffer), InsetCommandParams(BIBITEM_CODE));
// restore values of previously deleted item in this par.
if (!oldkey.empty())
inset->setParam("key", oldkey);
void Paragraph::deregisterWords()
{
+ map<Language, Private::Words>::const_iterator itl;
Private::Words::const_iterator it;
- WordList & wl = theWordList();
- for (it = d->words_.begin(); it != d->words_.end(); ++it)
- wl.remove(*it);
+ for (itl = d->words_.begin(); itl != d->words_.end(); ++itl) {
+ WordList * wl = theWordList(itl->first);
+ for (it = (itl->second).begin(); it != (itl->second).end(); ++it)
+ wl->remove(*it);
+ }
d->words_.clear();
}
locateWord(from, pos, WHOLE_WORD);
if (pos - from >= 6) {
docstring word = asString(from, pos, AS_STR_NONE);
- d->words_.insert(word);
+ FontList::const_iterator cit = d->fontlist_.fontIterator(pos);
+ if (cit == d->fontlist_.end())
+ return;
+ Language const * lang = cit->font().language();
+ d->words_[*lang].insert(word);
}
}
}
void Paragraph::registerWords()
{
+ map<Language, Private::Words>::const_iterator itl;
Private::Words::const_iterator it;
- WordList & wl = theWordList();
- for (it = d->words_.begin(); it != d->words_.end(); ++it)
- wl.insert(*it);
+ for (itl = d->words_.begin(); itl != d->words_.end(); ++itl) {
+ WordList * wl = theWordList(itl->first);
+ for (it = (itl->second).begin(); it != (itl->second).end(); ++it)
+ wl->insert(*it);
+ }
}
}
+string Paragraph::magicLabel() const
+{
+ stringstream ss;
+ ss << "magicparlabel-" << id();
+ return ss.str();
+}
+
+
} // namespace lyx