]> git.lyx.org Git - lyx.git/blobdiff - src/output_xhtml.cpp
Output keys with bibliography, too.
[lyx.git] / src / output_xhtml.cpp
index 8eabbc19ab8246b24a8f373ec52d52efd212eda6..fdf8681b56b8964946bbf3da2b89bbb8f2b3d412 100644 (file)
@@ -75,6 +75,66 @@ docstring htmlize(docstring const & str) {
 }
 
 
+string escapeChar(char c)
+{
+       string str;
+       switch (c) {
+       case ' ':
+               str += " ";
+               break;
+       case '&':
+               str += "&";
+               break;
+       case '<':
+               str += "&lt;";
+               break;
+       case '>':
+               str += "&gt;";
+               break;
+       default:
+               str += c;
+               break;
+       }
+       return str;
+}
+
+
+// escape what needs escaping
+string htmlize(string const & str) {
+       ostringstream d;
+       string::const_iterator it = str.begin();
+       string::const_iterator en = str.end();
+       for (; it != en; ++it)
+               d << escapeChar(*it);
+       return d.str();
+}
+
+
+string cleanAttr(string const & str)
+{
+       string newname;
+       string::const_iterator it = str.begin();
+       string::const_iterator en = str.end();
+       for (; it != en; ++it)
+               newname += isalnum(*it) ? *it : '_';
+       return newname; 
+}
+
+
+docstring cleanAttr(docstring const & str)
+{
+       docstring newname;
+       docstring::const_iterator it = str.begin();
+       docstring::const_iterator en = str.end();
+       for (; it != en; ++it)
+               if (isalnum(*it))
+                       newname += *it;
+               else
+                       newname += '_';
+       return newname; 
+}
+
+
 bool isFontTag(string const & s)
 {
        return s == "em" || s == "strong"; // others?
@@ -86,7 +146,7 @@ docstring StartTag::asTag() const
 {
        string output = "<" + tag_;
        if (!attr_.empty())
-               output += " " + attr_;
+               output += " " + html::htmlize(attr_);
        output += ">";
        return from_utf8(output);
 }
@@ -110,7 +170,7 @@ docstring CompTag::asTag() const
 {
        string output = "<" + tag_;
        if (!attr_.empty())
-               output += " " + attr_;
+               output += " " + html::htmlize(attr_);
        output += " />";
        return from_utf8(output);
 }
@@ -123,7 +183,7 @@ docstring CompTag::asTag() const
 ////////////////////////////////////////////////////////////////
 
 XHTMLStream::XHTMLStream(odocstream & os) 
-               :os_(os)
+               : os_(os), nextraw_(false)
 {}
 
 
@@ -143,6 +203,8 @@ void XHTMLStream::writeError(std::string const & s)
 
 bool XHTMLStream::closeFontTags()
 {
+       if (tag_stack_.empty())
+               return true;
        // first, we close any open font tags we can close
        StartTag curtag = tag_stack_.back();
        while (html::isFontTag(curtag.tag_)) {
@@ -185,7 +247,11 @@ void XHTMLStream::clearTagDeque()
 XHTMLStream & XHTMLStream::operator<<(docstring const & d)
 {
        clearTagDeque();
-       os_ << html::htmlize(d);
+       if (nextraw_) {
+               os_ << d;
+               nextraw_ = false;
+       } else
+               os_ << html::htmlize(d);
        return *this;
 }
 
@@ -193,7 +259,12 @@ XHTMLStream & XHTMLStream::operator<<(docstring const & d)
 XHTMLStream & XHTMLStream::operator<<(const char * s)
 {
        clearTagDeque();
-       os_ << html::htmlize(from_ascii(s));
+       docstring const d = from_ascii(s);
+       if (nextraw_) {
+               os_ << d;
+               nextraw_ = false;
+       } else
+               os_ << html::htmlize(d);
        return *this;
 }
 
@@ -201,7 +272,18 @@ XHTMLStream & XHTMLStream::operator<<(const char * s)
 XHTMLStream & XHTMLStream::operator<<(char_type c)
 {
        clearTagDeque();
-       os_ << html::escapeChar(c);
+       if (nextraw_) {
+               os_ << c;
+               nextraw_ = false;
+       } else
+               os_ << html::escapeChar(c);
+       return *this;
+}
+
+
+XHTMLStream & XHTMLStream::operator<<(NextRaw const &) 
+{ 
+       nextraw_ = true; 
        return *this;
 }
 
@@ -224,11 +306,12 @@ XHTMLStream & XHTMLStream::operator<<(CompTag const & tag)
        clearTagDeque();
        // tabs?
        os_ << tag.asTag();
+       cr();
        return *this;
 }
 
 
-bool   XHTMLStream::isTagOpen(string const & stag)
+bool XHTMLStream::isTagOpen(string const & stag)
 {
        TagStack::const_iterator sit = tag_stack_.begin();
        TagStack::const_iterator const sen = tag_stack_.end();
@@ -268,7 +351,8 @@ XHTMLStream & XHTMLStream::operator<<(EndTag const & etag)
                        if (dit->tag_ == etag.tag_) {
                                // it was pending, so we just erase it
                                writeError("Tried to close pending tag `" + etag.tag_ 
-                                       + "' when other tags were pending. Tag discarded.");
+                                       + "' when other tags were pending. Last pending tag is `"
+                                       + pending_tags_.back().tag_ + "'. Tag discarded.");
                                pending_tags_.erase(dit);
                                return *this;
                        }
@@ -475,12 +559,12 @@ ParagraphList::const_iterator makeParagraphs(Buffer const & buf,
                if (par != pbegin)
                        xs.cr();
 
-               // FIXME Should we really allow anything other than 'p' here?
-               
                // If we are already in a paragraph, and this is the first one, then we
                // do not want to open the paragraph tag.
-               bool const opened = 
-                       (par == pbegin && runparams.html_in_par) ? false : true;
+               // we also do not want to open it if the current layout does not permit
+               // multiple paragraphs.
+               bool const opened = runparams.html_make_pars &&
+                       (par != pbegin || !runparams.html_in_par);
                if (opened)
                        openTag(xs, lay);
                docstring const deferred = 
@@ -501,7 +585,7 @@ ParagraphList::const_iterator makeParagraphs(Buffer const & buf,
                        xs.cr();
                }
                if (!deferred.empty()) {
-                       xs << deferred;
+                       xs << XHTMLStream::NextRaw() << deferred;
                        xs.cr();
                }
        }
@@ -530,7 +614,8 @@ ParagraphList::const_iterator makeBibliography(Buffer const & buf,
 
 bool isNormalEnv(Layout const & lay)
 {
-       return lay.latextype == LATEX_ENVIRONMENT;
+       return lay.latextype == LATEX_ENVIRONMENT
+           || lay.latextype == LATEX_BIB_ENVIRONMENT;
 }
 
        
@@ -561,10 +646,13 @@ ParagraphList::const_iterator makeEnvironmentHtml(Buffer const & buf,
                // FIXME There may be a bug here about user defined enumeration
                // types. If so, then we'll need to take the counter and add "i",
                // "ii", etc, as with enum.
-               if (!style.counter.empty() && 
-                   (par == pbegin || !isNormalEnv(style))
-                   && style.latextype == LATEX_LIST_ENVIRONMENT)
-                       buf.params().documentClass().counters().step(style.counter);
+               Counters & cnts = buf.params().documentClass().counters();
+               docstring const & cntr = style.counter;
+               if (!style.counter.empty() 
+                   && (par == pbegin || !isNormalEnv(style)) 
+                               && cnts.hasCounter(cntr)
+               )
+                       cnts.step(cntr);
                ParagraphList::const_iterator send;
                // this will be positive, if we want to skip the initial word
                // (if it's been taken for the label).
@@ -583,7 +671,6 @@ ParagraphList::const_iterator makeEnvironmentHtml(Buffer const & buf,
                                        closeItemTag(xs, *lastlay);
                                        lastlay = 0;
                                }
-                               bool const labelfirst = style.htmllabelfirst();
                                if (isNormalEnv(style)) {
                                        // in this case, we print the label only for the first 
                                        // paragraph (as in a theorem).
@@ -599,12 +686,13 @@ ParagraphList::const_iterator makeEnvironmentHtml(Buffer const & buf,
                                                xs.cr();
                                        }
                                }       else { // some kind of list
+                                       bool const labelfirst = style.htmllabelfirst();
                                        if (!labelfirst)
                                                openItemTag(xs, style);
                                        if (style.labeltype == LABEL_MANUAL
                                            && style.htmllabeltag() != "NONE") {
                                                openLabelTag(xs, style);
-//                                             sep = par->firstWordLyXHTML(xs, runparams);
+                                               sep = par->firstWordLyXHTML(xs, runparams);
                                                closeLabelTag(xs, style);
                                                xs.cr();
                                        }
@@ -617,21 +705,15 @@ ParagraphList::const_iterator makeEnvironmentHtml(Buffer const & buf,
                                        }
                                        if (labelfirst)
                                                openItemTag(xs, style);
-                                       else
-                                               // FIXME This should probalby be put into the layout file rather 
-                                               // than hardcoded.
-                                               xs << StartTag("span", "class='" + to_utf8(style.name()) + "_inneritem'");
                                }
                                par->simpleLyXHTMLOnePar(buf, xs, runparams, 
-                                       text.outerFont(distance(begin, par)), sep);
-                               if (!isNormalEnv(style) && !labelfirst)
-                                       xs << EndTag("span");
+                                       text.outerFont(distance(begin, par)), false, sep);
                                ++par;
                                // We may not want to close the tag yet, in particular,
                                // if we're not at the end...
                                if (par != pend 
                                        //  and are doing items...
-                                        && style.latextype == LATEX_ITEM_ENVIRONMENT
+                                        && !isNormalEnv(style)
                                         // and if the depth has changed...
                                         && par->params().depth() != origdepth) {
                                         // then we'll save this layout for later, and close it when