// escape what needs escaping
-docstring htmlize(docstring const & str, XHTMLStream::EscapeSettings e) {
+docstring htmlize(docstring const & str, XHTMLStream::EscapeSettings e)
+{
odocstringstream d;
docstring::const_iterator it = str.begin();
docstring::const_iterator en = str.end();
// escape what needs escaping
-string htmlize(string const & str, XHTMLStream::EscapeSettings e) {
+string htmlize(string const & str, XHTMLStream::EscapeSettings e)
+{
ostringstream d;
string::const_iterator it = str.begin();
string::const_iterator en = str.end();
string::const_iterator it = str.begin();
string::const_iterator en = str.end();
for (; it != en; ++it)
- newname += isalnum(*it) ? *it : '_';
+ newname += isAlnumASCII(*it) ? *it : '_';
return newname;
}
bool isFontTag(string const & s)
{
- return s == "em" || s == "strong"; // others?
+ // others?
+ return s == "em" || s == "strong" || s == "i" || s == "b";
}
{}
-void XHTMLStream::cr()
+#if 0
+void XHTMLStream::dumpTagStack(string const & msg) const
{
- // tabs?
- os_ << from_ascii("\n");
+ writeError(msg + ": Tag Stack");
+ TagStack::const_reverse_iterator it = tag_stack_.rbegin();
+ TagStack::const_reverse_iterator en = tag_stack_.rend();
+ for (; it != en; ++it) {
+ writeError(it->tag_);
+ }
+ writeError("Pending Tags");
+ it = pending_tags_.rbegin();
+ en = pending_tags_.rend();
+ for (; it != en; ++it) {
+ writeError(it->tag_);
+ }
+ writeError("End Tag Stack");
}
+#endif
-void XHTMLStream::writeError(std::string const & s)
+void XHTMLStream::writeError(std::string const & s) const
{
LYXERR0(s);
- os_ << from_utf8("<!-- Output Error: " + s + " -->");
+ os_ << from_utf8("<!-- Output Error: " + s + " -->\n");
+}
+
+
+namespace {
+ // an illegal tag for internal use
+ static string const parsep_tag = "&LyX_parsep_tag&";
}
bool XHTMLStream::closeFontTags()
{
+ if (isTagPending(parsep_tag))
+ // we haven't had any content
+ return true;
+
+ // this may be a useless check, since we ought at least to have
+ // the parsep_tag. but it can't hurt too much to be careful.
if (tag_stack_.empty())
return true;
+
// first, we close any open font tags we can close
html::StartTag curtag = tag_stack_.back();
while (html::isFontTag(curtag.tag_)) {
return true;
curtag = tag_stack_.back();
}
- // so we've hit a non-font tag. let's see if any of the
- // remaining tags are font tags.
- TagStack::const_iterator it = tag_stack_.begin();
- TagStack::const_iterator en = tag_stack_.end();
- bool noFontTags = true;
+
+ if (curtag.tag_ == parsep_tag)
+ return true;
+
+ // so we've hit a non-font tag.
+ writeError("Tags still open in closeFontTags(). Probably not a problem,\n"
+ "but you might want to check these tags:");
+ TagStack::const_reverse_iterator it = tag_stack_.rbegin();
+ TagStack::const_reverse_iterator const en = tag_stack_.rend();
for (; it != en; ++it) {
- if (html::isFontTag(it->tag_)) {
- writeError("Font tag `" + it->tag_ + "' still open in closeFontTags().\n"
- "This is likely not a problem, but you might want to check.");
- noFontTags = false;
+ string const tagname = it->tag_;
+ if (tagname == parsep_tag)
+ break;
+ writeError(it->tag_);
+ }
+ return false;
+}
+
+
+void XHTMLStream::startParagraph(bool keep_empty)
+{
+ pending_tags_.push_back(html::StartTag(parsep_tag));
+ if (keep_empty)
+ clearTagDeque();
+}
+
+
+void XHTMLStream::endParagraph()
+{
+ if (isTagPending(parsep_tag)) {
+ // this case is normal. it just means we didn't have content,
+ // so the parsep_tag never got moved onto the tag stack.
+ while (!pending_tags_.empty()) {
+ // clear all pending tags up to and including the parsep tag.
+ // note that we work from the back, because we want to get rid
+ // of everything that hasn't been used.
+ html::StartTag const cur_tag = pending_tags_.back();
+ string const & tag = cur_tag.tag_;
+ pending_tags_.pop_back();
+ if (tag == parsep_tag)
+ break;
}
+ return;
+ }
+
+ if (!isTagOpen(parsep_tag)) {
+ writeError("No paragraph separation tag found in endParagraph().");
+ return;
+ }
+
+ // this case is also normal, if the parsep tag is the last one
+ // on the stack. otherwise, it's an error.
+ while (!tag_stack_.empty()) {
+ html::StartTag const cur_tag = tag_stack_.back();
+ string const & tag = cur_tag.tag_;
+ tag_stack_.pop_back();
+ if (tag == parsep_tag)
+ break;
+ writeError("Tag `" + tag + "' still open at end of paragraph. Closing.");
+ os_ << cur_tag.asEndTag();
}
- return noFontTags;
}
{
while (!pending_tags_.empty()) {
html::StartTag const & tag = pending_tags_.front();
- // tabs?
- os_ << tag.asTag();
+ if (tag.tag_ != parsep_tag)
+ // tabs?
+ os_ << tag.asTag();
tag_stack_.push_back(tag);
pending_tags_.pop_front();
}
clearTagDeque();
// tabs?
os_ << tag.asTag();
- cr();
+ *this << html::CR();
+ return *this;
+}
+
+
+XHTMLStream & XHTMLStream::operator<<(html::CR const &)
+{
+ // tabs?
+ os_ << from_ascii("\n");
return *this;
}
-bool XHTMLStream::isTagOpen(string const & stag)
+bool XHTMLStream::isTagOpen(string const & stag) const
{
TagStack::const_iterator sit = tag_stack_.begin();
TagStack::const_iterator const sen = tag_stack_.end();
}
+bool XHTMLStream::isTagPending(string const & stag) const
+{
+ TagStack::const_iterator sit = pending_tags_.begin();
+ TagStack::const_iterator const sen = pending_tags_.end();
+ for (; sit != sen; ++sit)
+ if (sit->tag_ == stag)
+ return true;
+ return false;
+}
+
+
// this is complicated, because we want to make sure that
// everything is properly nested. the code ought to make
// sure of that, but we won't assert (yet) if we run into
html::StartTag curtag = tag_stack_.back();
while (curtag.tag_ != etag.tag_) {
writeError(curtag.tag_);
- os_ << curtag.asEndTag();
+ if (curtag.tag_ != parsep_tag)
+ os_ << curtag.asEndTag();
tag_stack_.pop_back();
curtag = tag_stack_.back();
}
// FIXME We should see if there's a label to be output and
// do something with it.
if (par != pbegin)
- xs.cr();
+ xs << html::CR();
// If we are already in a paragraph, and this is the first one, then we
// do not want to open the paragraph tag.
// (ii) We didn't open it and html_in_par is true,
// but we are in the first par, and there is a next par.
ParagraphList::const_iterator nextpar = par;
- nextpar++;
+ ++nextpar;
bool const needclose =
(opened && (!runparams.html_in_par || nextpar != pend))
|| (!opened && runparams.html_in_par && par == pbegin && nextpar != pend);
if (needclose) {
closeTag(xs, lay);
- xs.cr();
+ xs << html::CR();
}
if (!deferred.empty()) {
- xs << XHTMLStream::ESCAPE_NONE << deferred;
- xs.cr();
+ xs << XHTMLStream::ESCAPE_NONE << deferred << html::CR();
}
}
return pend;
{
// FIXME XHTML
// Use TextClass::htmlTOCLayout() to figure out how we should look.
- xs << html::StartTag("h2", "class='bibliography'");
- xs << pbegin->layout().labelstring(false);
- xs << html::EndTag("h2");
- xs.cr();
- xs << html::StartTag("div", "class='bibliography'");
- xs.cr();
+ xs << html::StartTag("h2", "class='bibliography'")
+ << pbegin->layout().labelstring(false)
+ << html::EndTag("h2")
+ << html::CR()
+ << html::StartTag("div", "class='bibliography'")
+ << html::CR();
makeParagraphs(buf, xs, runparams, text, pbegin, pend);
xs << html::EndTag("div");
return pend;
// open tag for this environment
openTag(xs, bstyle);
- xs.cr();
+ xs << html::CR();
// we will on occasion need to remember a layout from before.
Layout const * lastlay = 0;
xs << lbl;
closeLabelTag(xs, style);
}
- xs.cr();
+ xs << html::CR();
}
} else { // some kind of list
if (style.labeltype == LABEL_MANUAL) {
openLabelTag(xs, style);
sep = par->firstWordLyXHTML(xs, runparams);
closeLabelTag(xs, style);
- xs.cr();
+ xs << html::CR();
}
else {
openLabelTag(xs, style);
xs << par->params().labelString();
closeLabelTag(xs, style);
- xs.cr();
+ xs << html::CR();
}
}
} // end label output
lastlay = &style;
} else
closeItemTag(xs, style);
- xs.cr();
+ xs << html::CR();
}
// The other possibility is that the depth has increased, in which
// case we need to recurse.
if (lastlay != 0)
closeItemTag(xs, *lastlay);
closeTag(xs, bstyle);
- xs.cr();
+ xs << html::CR();
return pend;
}
void makeCommand(Buffer const & buf,
- XHTMLStream & xs,
- OutputParams const & runparams,
- Text const & text,
- ParagraphList::const_iterator const & pbegin)
+ XHTMLStream & xs,
+ OutputParams const & runparams,
+ Text const & text,
+ ParagraphList::const_iterator const & pbegin)
{
Layout const & style = pbegin->layout();
if (!style.counter.empty())
pbegin->simpleLyXHTMLOnePar(buf, xs, runparams,
text.outerFont(distance(begin, pbegin)));
closeTag(xs, style);
- xs.cr();
+ xs << html::CR();
}
} // end anonymous namespace
OutputParams const & runparams)
{
ParagraphList const & paragraphs = text.paragraphs();
- ParagraphList::const_iterator par = paragraphs.begin();
- ParagraphList::const_iterator pend = paragraphs.end();
+ if (runparams.par_begin == runparams.par_end) {
+ runparams.par_begin = 0;
+ runparams.par_end = paragraphs.size();
+ }
+ pit_type bpit = runparams.par_begin;
+ pit_type const epit = runparams.par_end;
+ LASSERT(bpit < epit, /* */);
OutputParams ourparams = runparams;
- while (par != pend) {
+ ParagraphList::const_iterator const pend =
+ (epit == (int) paragraphs.size()) ?
+ paragraphs.end() : paragraphs.constIterator(epit);
+ while (bpit < epit) {
+ ParagraphList::const_iterator par = paragraphs.constIterator(bpit);
if (par->params().startOfAppendix()) {
- // FIXME: only the counter corresponding to toplevel
- // sectioning should be reset
- Counters & cnts = buf.masterBuffer()->params().documentClass().counters();
- cnts.reset();
- cnts.appendix(true);
+ // We want to reset the counter corresponding to toplevel sectioning
+ Layout const & lay =
+ buf.masterBuffer()->params().documentClass().getTOCLayout();
+ docstring const cnt = lay.counter;
+ if (!cnt.empty()) {
+ Counters & cnts =
+ buf.masterBuffer()->params().documentClass().counters();
+ cnts.reset(cnt);
+ }
}
Layout const & style = par->layout();
- ParagraphList::const_iterator lastpar = par;
+ ParagraphList::const_iterator const lastpar = par;
ParagraphList::const_iterator send;
switch (style.latextype) {
par = makeParagraphs(buf, xs, ourparams, text, par, send);
break;
}
- // FIXME??
- // makeEnvironment may process more than one paragraphs and bypass pend
- if (distance(lastpar, par) >= distance(lastpar, pend))
- break;
+ bpit += distance(lastpar, par);
}
}
-string alignmentToCSS(LyXAlignment align) {
+string alignmentToCSS(LyXAlignment align)
+{
switch (align) {
case LYX_ALIGN_BLOCK:
// we are NOT going to use text-align: justify!!