]> git.lyx.org Git - lyx.git/blobdiff - src/buffer.C
Applied Angus patch to compile on DEC C++ and to avoid name clashes
[lyx.git] / src / buffer.C
index 90a4b8f53f281880689e3fbd8e7f54b0d751ad6a..f13af04fe5d5e8f80fdad47a6b54a56e4339414c 100644 (file)
@@ -17,6 +17,8 @@
 #include <fstream>
 #include <iomanip>
 #include <map>
+#include <stack>
+#include <list>
 
 #include <cstdlib>
 #include <cmath>
@@ -111,14 +113,19 @@ using std::vector;
 using std::map;
 using std::max;
 using std::set;
+using std::stack;
+using std::list;
 
 // all these externs should eventually be removed.
 extern BufferList bufferlist;
 
 extern LyXAction lyxaction;
 
+namespace {
 
-static const int LYX_FORMAT = 218;
+const int LYX_FORMAT = 218;
+
+} // namespace anon
 
 extern int tex_code_break_column;
 
@@ -352,7 +359,11 @@ bool Buffer::readLyXformat2(LyXLex & lex, LyXParagraph * par)
 
 
 // We'll remove this later. (Lgb)
-static string last_inset_read;
+namespace {
+
+string last_inset_read;
+
+} // anon
 
 
 bool
@@ -366,20 +377,27 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
 #endif
        )
 {
+       bool the_end_read = false;
+#ifndef NO_PEXTRA_REALLY
 #ifdef NEW_INSETS
        // This is super temporary but is needed to get the compability
        // mode for minipages work correctly together with new tabulars.
        static int call_depth = 0;
        ++call_depth;
 #endif
-       bool the_end_read = false;
+       bool checkminipage = false;
+       static LyXParagraph * minipar = 0;
+       static LyXParagraph * parBeforeMinipage = 0;
+#endif
        
        if (token[0] != '\\') {
                for (string::const_iterator cit = token.begin();
-                    cit != token.end(); ++cit) {
+                    cit != token.end(); ++cit)
+               {
                        par->InsertChar(pos, (*cit), font);
                        ++pos;
                }
+               checkminipage = true;
        } else if (token == "\\i") {
                Inset * inset = new InsetLatexAccent;
                inset->Read(this, lex);
@@ -479,117 +497,6 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
                        ++pos;
                } else {
 #endif
-                       // BEGIN pextra_minipage compability
-                       // This should be removed in 1.3.x (Lgb)
-                       
-                       // This compability code is not perfect. In a couple
-                       // of rand cases it fails. When the minipage par is
-                       // the first par in the document, and when there are
-                       // none or only one regular paragraphs after the
-                       // minipage. Currently I am not investing any effort
-                       // in fixing those cases.
-                       static LyXParagraph * minipar = 0;
-                       //lyxerr << "Call depth: " << call_depth << endl;
-                       if (call_depth == 1) {
-                               
-                       if (minipar
-                           && par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
-                               lyxerr << "minipages in a row" << endl;
-                               if (par->params.pextraStartMinipage()) {
-                                       lyxerr << "start new minipage" << endl;
-                                       // minipages in a row
-                                       par->previous()->next(0);
-                                       par->previous(minipar->previous());
-                                       minipar->previous()->next(par);
-                                       minipar->previous(0);
-                                       
-                                       // Before we insert the list of
-                                       // minipages into the inset we have
-                                       // to clean up a bit.
-                                       // This is not quite correct yet since
-                                       // we do want to use some of these
-                                       // parameters to set options in the
-                                       // minipage inset.
-                                       LyXParagraph * tmp = minipar;
-                                       while (tmp) {
-                                               tmp->params.pextraType(0);
-                                               tmp->params.pextraWidth(string());
-                                               tmp->params.pextraWidthp(string());
-                                               tmp->params.pextraAlignment(0);
-                                               tmp->params.pextraHfill(false);
-                                               tmp->params.pextraStartMinipage(false);
-                                               tmp = tmp->next();
-                                       }
-                                       
-                                       InsetMinipage * mini = new InsetMinipage;
-                                       mini->inset->par = minipar;
-                                       // Insert the minipage last in the
-                                       // previous paragraph.
-                                       par->previous()->InsertInset(par->previous()->size(), mini);
-                                       minipar = par;
-                               } else {
-                                       lyxerr << "new minipage par" << endl;
-                                       //nothing to do just continue reading
-                               }
-                               
-                       } else if (minipar) {
-                               lyxerr << "last minipage par read" << endl;
-                               // The last paragraph read was not part of a
-                               // minipage but the par linked list is...
-                               // So we need to remove the last par from the
-                               // rest, insert the rest of the paragraphs into
-                               // a InsetMinipage, insert this minipage into
-                               // prevpar, append the current par to prevpar
-                               // and continue...
-
-                               LyXParagraph * lp = minipar;
-                               int pcount = 0;
-                               while (lp) {
-                                       ++pcount;
-                                       lp = lp->next();
-                               }
-                               lyxerr << "Minipar count: " << pcount << endl;
-                               lyxerr << "Par: " << (void*)par << endl;
-                               lyxerr << "Par->prev: " << (void*)par->previous() << endl;
-
-                               if (par->previous())
-                                       par->previous()->next(0);
-                               par->previous(minipar->previous());
-                               minipar->previous()->next(par);
-                               minipar->previous(0);
-                               
-                               // Before we insert the list of
-                               // minipages into the inset we have
-                               // to clean up a bit.
-                               // This is not quite correct yet since we
-                               // do want to use some of these parameters
-                               // to set options in the minipage inset.
-                               LyXParagraph * tmp = minipar;
-                               while (tmp) {
-                                       tmp->params.pextraType(0);
-                                       tmp->params.pextraWidth(string());
-                                       tmp->params.pextraWidthp(string());
-                                       tmp->params.pextraAlignment(0);
-                                       tmp->params.pextraHfill(false);
-                                       tmp->params.pextraStartMinipage(false);
-                                       tmp = tmp->next();
-                               }
-                               
-                               InsetMinipage * mini = new InsetMinipage;
-                               mini->inset->par = minipar;
-                               par->previous()->InsertInset(par->previous()->size(), mini);
-                               minipar = 0;
-                       } else if (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE) {
-                               
-                               // par is the first paragraph in a minipage
-                               lyxerr << "begin minipage" << endl;
-                               minipar = par;
-                               
-                       }
-                       }
-                       
-                       // End of pextra_minipage compability
-                       
                        if (!return_par)
                                return_par = par;
                        else {
@@ -1077,6 +984,7 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
        } else if (token == "\\added_space_bottom") {
                lex.nextToken();
                par->params.spaceBottom(VSpace(lex.GetString()));
+#ifndef NO_PEXTRA_REALLY
        } else if (token == "\\pextra_type") {
                lex.nextToken();
                par->params.pextraType(lex.GetInteger());
@@ -1095,6 +1003,7 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
        } else if (token == "\\pextra_start_minipage") {
                lex.nextToken();
                par->params.pextraStartMinipage(lex.GetInteger());
+#endif
        } else if (token == "\\labelwidthstring") {
                lex.EatLine();
                par->params.labelWidthString(lex.GetString());
@@ -1145,6 +1054,9 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
                inset->Read(this, lex);
                par->InsertInset(pos, inset, font);
                ++pos;
+               // because of OLD_TABULAR_READ where tabulars have been
+               // one paragraph.
+               checkminipage = true;
        } else if (token == "\\hfill") {
                par->InsertChar(pos, LyXParagraph::META_HFILL, font);
                ++pos;
@@ -1174,6 +1086,7 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
                ++pos;
        } else if (token == "\\the_end") {
                the_end_read = true;
+               minipar = parBeforeMinipage = 0;
        } else {
                // This should be insurance for the future: (Asger)
                lex.printError("Unknown token `$$Token'. "
@@ -1185,6 +1098,143 @@ Buffer::parseSingleLyXformat2Token(LyXLex & lex, LyXParagraph *& par,
                        ++pos;
                }
        }
+#ifndef NO_PEXTRA_REALLY
+       // now check if we have a minipage paragraph as at this
+       // point we already read all the necessary data!
+       // this cannot be done in layout because there we did
+       // not read yet the paragraph PEXTRA-params (Jug)
+       //
+       // BEGIN pextra_minipage compability
+       // This should be removed in 1.3.x (Lgb)
+       
+       // This compability code is not perfect. In a couple
+       // of rand cases it fails. When the minipage par is
+       // the first par in the document, and when there are
+       // none or only one regular paragraphs after the
+       // minipage. Currently I am not investing any effort
+       // in fixing those cases.
+
+       //lyxerr << "Call depth: " << call_depth << endl;
+       if (checkminipage && (call_depth == 1)) {
+       checkminipage = false;
+       if (minipar && (minipar != par) &&
+           (par->params.pextraType()==LyXParagraph::PEXTRA_MINIPAGE))
+       {
+               lyxerr << "minipages in a row" << endl;
+               if (par->params.pextraStartMinipage()) {
+                       lyxerr << "start new minipage" << endl;
+                       // minipages in a row
+                       par->previous()->next(0);
+                       par->previous(0);
+                               
+                       LyXParagraph * tmp = minipar;
+                       while (tmp) {
+                               tmp->params.pextraType(0);
+                               tmp->params.pextraWidth(string());
+                               tmp->params.pextraWidthp(string());
+                               tmp->params.pextraAlignment(0);
+                               tmp->params.pextraHfill(false);
+                               tmp->params.pextraStartMinipage(false);
+                               tmp = tmp->next();
+                       }
+                       // create a new paragraph to insert the
+                       // minipages in the following case
+                       if (par->params.pextraStartMinipage() &&
+                           !par->params.pextraHfill())
+                       {
+                               LyXParagraph * p = new LyXParagraph;
+                               p->layout = 0;
+                               p->previous(parBeforeMinipage);
+                               parBeforeMinipage->next(p);
+                               p->next(0);
+                               p->params.depth(parBeforeMinipage->params.depth());
+                               parBeforeMinipage = p;
+                       }
+                       InsetMinipage * mini = new InsetMinipage;
+                       mini->pos(static_cast<InsetMinipage::Position>(par->params.pextraAlignment()));
+                       mini->width(par->params.pextraWidth());
+                       mini->widthp(par->params.pextraWidthp());
+                       mini->inset->par = par;
+                       // Insert the minipage last in the
+                       // previous paragraph.
+                       if (par->params.pextraHfill()) {
+                               parBeforeMinipage->InsertChar
+                                       (parBeforeMinipage->size(), LyXParagraph::META_HFILL);
+                       }
+                       parBeforeMinipage->InsertInset
+                               (parBeforeMinipage->size(), mini);
+                               
+                       minipar = par;
+               } else {
+                       lyxerr << "new minipage par" << endl;
+                       //nothing to do just continue reading
+               }
+                       
+       } else if (minipar && (minipar != par)) {
+               lyxerr << "last minipage par read" << endl;
+               // The last paragraph read was not part of a
+               // minipage but the par linked list is...
+               // So we need to remove the last par from the
+               // rest
+               if (par->previous())
+                       par->previous()->next(0);
+               par->previous(parBeforeMinipage);
+               parBeforeMinipage->next(par);
+               LyXParagraph * tmp = minipar;
+               while (tmp) {
+                       tmp->params.pextraType(0);
+                       tmp->params.pextraWidth(string());
+                       tmp->params.pextraWidthp(string());
+                       tmp->params.pextraAlignment(0);
+                       tmp->params.pextraHfill(false);
+                       tmp->params.pextraStartMinipage(false);
+                       tmp = tmp->next();
+               }
+               depth = parBeforeMinipage->params.depth();
+               minipar = parBeforeMinipage = 0;
+       } else if (!minipar &&
+                  (par->params.pextraType() == LyXParagraph::PEXTRA_MINIPAGE))
+       {
+               // par is the first paragraph in a minipage
+               lyxerr << "begin minipage" << endl;
+               // To minimize problems for
+               // the users we will insert
+               // the first minipage in
+               // a sequence of minipages
+               // in its own paragraph.
+               LyXParagraph * p = new LyXParagraph;
+               p->layout = 0;
+               p->previous(par->previous());
+               p->next(0);
+               p->params.depth(depth);
+               par->params.depth(0);
+               depth = 0;
+               if (par->previous())
+                       par->previous()->next(p);
+               par->previous(0);
+               parBeforeMinipage = p;
+               minipar = par;
+               if (!return_par || (return_par == par))
+                       return_par = p;
+
+               InsetMinipage * mini = new InsetMinipage;
+               mini->pos(static_cast<InsetMinipage::Position>(minipar->params.pextraAlignment()));
+               mini->width(minipar->params.pextraWidth());
+               mini->widthp(minipar->params.pextraWidthp());
+               mini->inset->par = minipar;
+                       
+               // Insert the minipage last in the
+               // previous paragraph.
+               if (minipar->params.pextraHfill()) {
+                       parBeforeMinipage->InsertChar
+                               (parBeforeMinipage->size(),LyXParagraph::META_HFILL);
+               }
+               parBeforeMinipage->InsertInset
+                       (parBeforeMinipage->size(), mini);
+       }
+       }
+       // End of pextra_minipage compability
+#endif
        --call_depth;
        return the_end_read;
 }
@@ -2309,7 +2359,10 @@ void Buffer::latexParagraphs(ostream & ofs, LyXParagraph * par,
                // flag this with ftcount
                ftcount = -1;
                if (layout.isEnvironment()
-                    || par->params.pextraType() != LyXParagraph::PEXTRA_NONE) {
+#ifndef NEW_INSETS
+                    || par->params.pextraType() != LyXParagraph::PEXTRA_NONE
+#endif
+                       ) {
                        par = par->TeXEnvironment(this, params, ofs, texrow
 #ifndef NEW_INSETS
                                                  ,ftnote, ft_texrow, ftcount
@@ -2383,7 +2436,7 @@ bool Buffer::isSGML() const
 void Buffer::sgmlOpenTag(ostream & os, int depth,
                         string const & latexname) const
 {
-       if (latexname != "!-- --")
+       if (!latexname.empty() && latexname != "!-- --")
                os << string(depth, ' ') << "<" << latexname << ">\n";
 }
 
@@ -2391,23 +2444,13 @@ void Buffer::sgmlOpenTag(ostream & os, int depth,
 void Buffer::sgmlCloseTag(ostream & os, int depth,
                          string const & latexname) const
 {
-       if (latexname != "!-- --")
+       if (!latexname.empty() && latexname != "!-- --")
                os << string(depth, ' ') << "</" << latexname << ">\n";
 }
 
 
 void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 {
-       LyXParagraph * par = paragraph;
-
-       niceFile = nice; // this will be used by Insetincludes.
-
-       string top_element = textclasslist.LatexnameOfClass(params.textclass);
-       string environment_stack[10];
-        string item_name;
-
-       int depth = 0; // paragraph depth
-
        ofstream ofs(fname.c_str());
 
        if (!ofs) {
@@ -2415,19 +2458,18 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                return;
        }
 
+       niceFile = nice; // this will be used by included files.
+
         LyXTextClass const & tclass =
                textclasslist.TextClass(params.textclass);
 
        LaTeXFeatures features(params, tclass.numLayouts());
        validate(features);
 
-       //if (nice)
-       tex_code_break_column = lyxrc.ascii_linelen;
-       //else
-       //tex_code_break_column = 0;
-
        texrow.reset();
 
+       string top_element = textclasslist.LatexnameOfClass(params.textclass);
+
        if (!body_only) {
                string sgml_includedfiles=features.getIncludedFiles(fname);
 
@@ -2452,8 +2494,12 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
            << " created this file. For more info see http://www.lyx.org/"
            << " -->\n";
 
+       int depth = 0; // paragraph depth
+       LyXParagraph * par = paragraph;
+        string item_name;
+       vector<string> environment_stack(5);
+
        while (par) {
-               int desc_on = 0; // description mode
                LyXLayout const & style =
                        textclasslist.Style(params.textclass,
                                            par->layout);
@@ -2516,9 +2562,7 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                case LATEX_ENVIRONMENT:
                case LATEX_ITEM_ENVIRONMENT:
                        if (depth == par->params.depth() 
-                          && environment_stack[depth] != style.latexname()
-                          && !environment_stack[depth].empty()) {
-
+                           && environment_stack[depth] != style.latexname()) {
                                sgmlCloseTag(ofs, depth,
                                             environment_stack[depth]);
                                environment_stack[depth].erase();
@@ -2529,18 +2573,21 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
                        }
                        if (environment_stack[depth] != style.latexname()) {
                                if (depth == 0) {
-                                       string const temp = "p";
-                                       sgmlOpenTag(ofs, depth, temp);
+                                       sgmlOpenTag(ofs, depth, "p");
                                }
+                               sgmlOpenTag(ofs, depth, style.latexname());
+
+                               if (environment_stack.size() == depth+1)
+                                       environment_stack.push_back("!-- --");
                                environment_stack[depth] = style.latexname();
-                               sgmlOpenTag(ofs, depth,
-                                           environment_stack[depth]);
                        }
-                       if (style.latextype == LATEX_ENVIRONMENT) break;
 
-                       desc_on = (style.labeltype == LABEL_MANUAL);
+                       if (style.latexparam() == "CDATA")
+                               ofs << "<![CDATA[";
 
-                       if (desc_on)
+                       if (style.latextype == LATEX_ENVIRONMENT) break;
+
+                       if (style.labeltype == LABEL_MANUAL)
                                item_name = "tag";
                        else
                                item_name = "item";
@@ -2554,24 +2601,27 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
 
 #ifndef NEW_INSETS
                do {
-                       SimpleLinuxDocOnePar(ofs, par, desc_on, depth);
+                       SimpleLinuxDocOnePar(ofs, par, depth);
                        
                        par = par->next_;
                        linuxDocHandleFootnote(ofs, par, depth);
                }
                while(par && par->IsDummy());
 #else
-                       SimpleLinuxDocOnePar(ofs, par, desc_on, depth);
+               SimpleLinuxDocOnePar(ofs, par, depth);
 
-                       par = par->next();
+               par = par->next();
 #endif
 
                ofs << "\n";
                // write closing SGML tags
                switch (style.latextype) {
                case LATEX_COMMAND:
+                       break;
                case LATEX_ENVIRONMENT:
                case LATEX_ITEM_ENVIRONMENT:
+                       if (style.latexparam() == "CDATA")
+                               ofs << "]]>";
                        break;
                default:
                        sgmlCloseTag(ofs, depth, style.latexname());
@@ -2580,11 +2630,8 @@ void Buffer::makeLinuxDocFile(string const & fname, bool nice, bool body_only)
        }
    
        // Close open tags
-       for (; depth > 0; --depth)
-               sgmlCloseTag(ofs, depth, environment_stack[depth]);
-
-       if (!environment_stack[depth].empty())
-               sgmlCloseTag(ofs, depth, environment_stack[depth]);
+       for (int i=depth; i >= 0; --i)
+               sgmlCloseTag(ofs, depth, environment_stack[i]);
 
        if (!body_only) {
                ofs << "\n\n";
@@ -2743,244 +2790,229 @@ void Buffer::DocBookHandleFootnote(ostream & os, LyXParagraph * & par,
 #endif
 
 
-// push a tag in a style stack
-void Buffer::push_tag(ostream & os, string const & tag,
-                     int & pos, char stack[5][3])
-{
-#ifdef WITH_WARNINGS
-#warning Use a real stack! (Lgb)
-#endif
-       // pop all previous tags
-       for (int j = pos; j >= 0; --j)
-               os << "</" << stack[j] << ">";
+// checks, if newcol chars should be put into this line
+// writes newline, if necessary.
+namespace {
 
-       // add new tag
-       sprintf(stack[++pos], "%s", tag.c_str());
+void linux_doc_line_break(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
+       }
+}
 
-       // push all tags
-       for (int i = 0; i <= pos; ++i)
-               os << "<" << stack[i] << ">";
+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 "";
 }
 
 
-void Buffer::pop_tag(ostream & os, string const & tag,
-                     int & pos, char stack[5][3])
+inline
+void operator|=(PAR_TAG & p1, PAR_TAG const & p2)
 {
-#ifdef WITH_WARNINGS
-#warning Use a real stack! (Lgb)
-#endif
-       // Please, Lars, do not remove the global variable. I already
-       // had to reintroduce it twice! (JMarc)
-       // but...but... I'll remove it anyway. (well not quite) (Lgb)
-#if 0
-       int j;
-       
-        // pop all tags till specified one
-        for (j = pos; (j >= 0) && tag != stack[j]; --j)
-                os << "</" << stack[j] << ">";
+        p1 = static_cast<PAR_TAG>(p1 | p2);
+}
 
-        // closes the tag
-        os << "</" << tag << ">";
-       
-        // push all tags, but the specified one
-        for (j = j + 1; j <= pos; ++j) {
-                os << "<" << stack[j] << ">";
-                strcpy(stack[j - 1], stack[j]);
-        }
-        --pos;
-#else
-        // pop all tags till specified one
-       int j = pos;
-        for (int j = pos; (j >= 0) && tag != stack[j]; --j)
-                os << "</" << stack[j] << ">";
 
-        // closes the tag
-        os << "</" << tag << ">";
-       
-        // push all tags, but the specified one
-        for (int i = j + 1; i <= pos; ++i) {
-                os << "<" << stack[i] << ">";
-                strcpy(stack[i - 1], stack[i]);
-        }
-        --pos;
-#endif
+inline
+void reset(PAR_TAG & p1, PAR_TAG const & p2)
+{
+       p1 = static_cast<PAR_TAG>( p1 & ~p2);
 }
 
+} // namespace anon
 
-// Handle internal paragraph parsing -- layout already processed.
 
-// checks, if newcol chars should be put into this line
-// writes newline, if necessary.
-static
-void linux_doc_line_break(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
-       }
-}
 
 
-void Buffer::SimpleLinuxDocOnePar(ostream & os, LyXParagraph * par,
-                                 int desc_on, int /*depth*/)
+// Handle internal paragraph parsing -- layout already processed.
+void Buffer::SimpleLinuxDocOnePar(ostream & os,
+                                 LyXParagraph * par, int /*depth*/)
 {
-       LyXFont font1;
-       char c;
-       Inset * inset;
-       LyXParagraph::size_type main_body;
-       int j;
        LyXLayout const & style = textclasslist.Style(params.textclass,
                                                      par->GetLayout());
-
-       char family_type = 0;               // family font flag 
-       bool is_bold     = false;           // series font flag 
-       char shape_type  = 0;               // shape font flag 
-       bool is_em = false;                 // emphasis (italic) font flag 
-
-       int stack_num = -1;          // style stack position
-       // Can this be rewritten to use a std::stack, please. (Lgb)
-       char stack[5][3];            // style stack 
         string::size_type char_line_count = 5;     // Heuristic choice ;-) 
 
-       if (style.labeltype != LABEL_MANUAL)
-               main_body = 0;
-       else
-               main_body = par->BeginningOfMainBody();
-
        // gets paragraph main font
-       if (main_body > 0)
-               font1 = style.labelfont;
-       else
-               font1 = style.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 < PAR_TAG > tag_state;
        // parsing main loop
-       for (LyXParagraph::size_type i = 0;
-            i < par->size(); ++i) {
+       for (LyXParagraph::size_type i = 0; i < par->size(); ++i) {
 
-               // handle quote tag
-               if (i == main_body
-#ifndef NEW_INSETS
-                   && !par->IsDummy()
-#endif
-                       ) {
-                       if (main_body > 0)
-                               font1 = style.font;
-               }
+               PAR_TAG tag_close = NONE;
+               list < PAR_TAG > tag_open;
 
-               LyXFont const font2 = par->getFont(params, i);
+               LyXFont const font = par->getFont(params, i);
 
-               if (font1.family() != font2.family()) {
+               if (font_old.family() != font.family()) {
                        switch (family_type) {
-                       case 0:
-                               if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
-                                       push_tag(os, "tt", stack_num, stack);
-                                       family_type = 1;
-                               }
-                               else if (font2.family() == LyXFont::SANS_FAMILY) {
-                                       push_tag(os, "sf", stack_num, stack);
-                                       family_type = 2;
-                               }
+                       case LyXFont::SANS_FAMILY:
+                               tag_close |= SF;
                                break;
-                       case 1:
-                               pop_tag(os, "tt", stack_num, stack);
-                               if (font2.family() == LyXFont::SANS_FAMILY) {
-                                       push_tag(os, "sf", stack_num, stack);
-                                       family_type = 2;
-                               } else {
-                                       family_type = 0;
-                               }
+                       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;
-                       case 2:
-                               pop_tag(os, "sf", stack_num, stack);
-                               if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
-                                       push_tag(os, "tt", stack_num, stack);
-                                       family_type = 1;
-                               } else {
-                                       family_type = 0;
-                               }
                        }
                }
 
-               // handle bold face
-               if (font1.series() != font2.series()) {
-                       if (font2.series() == LyXFont::BOLD_SERIES) {
-                               push_tag(os, "bf", stack_num, stack);
-                               is_bold = true;
-                       } else if (is_bold) {
-                               pop_tag(os, "bf", stack_num, stack);
-                               is_bold = false;
+               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;
                        }
+
                }
 
-               // handle italic and slanted fonts
-               if (font1.shape() != font2.shape()) {
+               if (font_old.shape() != font.shape()) {
                        switch (shape_type) {
-                       case 0:
-                               if (font2.shape() == LyXFont::ITALIC_SHAPE) {
-                                       push_tag(os, "it", stack_num, stack);
-                                       shape_type = 1;
-                               } else if (font2.shape() == LyXFont::SLANTED_SHAPE) {
-                                       push_tag(os, "sl", stack_num, stack);
-                                       shape_type = 2;
-                               }
+                       case LyXFont::ITALIC_SHAPE:
+                               tag_close |= IT;
                                break;
-                       case 1:
-                               pop_tag(os, "it", stack_num, stack);
-                               if (font2.shape() == LyXFont::SLANTED_SHAPE) {
-                                       push_tag(os, "sl", stack_num, stack);
-                                       shape_type = 2;
-                               } else {
-                                       shape_type = 0;
-                               }
+                       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;
-                       case 2:
-                               pop_tag(os, "sl", stack_num, stack);
-                               if (font2.shape() == LyXFont::ITALIC_SHAPE) {
-                                       push_tag(os, "it", stack_num, stack);
-                                       shape_type = 1;
-                               } else {
-                                       shape_type = 0;
-                               }
                        }
                }
                // handle <em> tag
-               if (font1.emph() != font2.emph()) {
-                       if (font2.emph() == LyXFont::ON) {
-                               push_tag(os, "em", stack_num, stack);
+               if (font_old.emph() != font.emph()) {
+                       if (font.emph() == LyXFont::ON) {
+                               tag_open.push_back(EM);
                                is_em = true;
-                       } else if (is_em) {
-                               pop_tag(os, "em", stack_num, stack);
+                       }
+                       else if (is_em) {
+                               tag_close |= EM;
                                is_em = false;
                        }
                }
 
-               c = par->GetChar(i);
+               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 == LyXParagraph::META_INSET) {
-                       inset = par->GetInset(i);
+                       Inset * inset = par->GetInset(i);
                        inset->Linuxdoc(this, os);
+                       font_old = font;
+                       continue;
                }
 
-               if (font2.latex() == LyXFont::ON) {
+               if (font.latex() == LyXFont::ON || style.latexparam() == "CDATA") {
                        // "TeX"-Mode on == > SGML-Mode on.
                        if (c != '\0')
-                               os << c; // see LaTeX-Generation...
+                               os << c;
                        ++char_line_count;
                } else {
                        string sgml_string;
                        if (par->linuxDocConvertChar(c, sgml_string)
-                           && !style.free_spacing) { // in freespacing
-                                                    // mode, spaces are
-                                                    // non-breaking characters
-                               // char is ' '
-                               if (desc_on == 1) {
+                           && !style.free_spacing) { 
+                               // in freespacing mode, spaces are
+                               // non-breaking characters
+                               if (desc_on) {// if char is ' ' then...
+
                                        ++char_line_count;
                                        linux_doc_line_break(os, char_line_count, 6);
                                        os << "</tag>";
-                                       desc_on = 2;
+                                       desc_on = false;
                                } else  {
                                        linux_doc_line_break(os, char_line_count, 1);
                                        os << c;
@@ -2990,32 +3022,19 @@ void Buffer::SimpleLinuxDocOnePar(ostream & os, LyXParagraph * par,
                                char_line_count += sgml_string.length();
                        }
                }
-               font1 = font2;
-       }
-
-       // needed if there is an optional argument but no contents
-       if (main_body > 0 && main_body == par->size()) {
-               font1 = style.font;
+               font_old = font;
        }
 
-       // pop all defined Styles
-       for (j = stack_num; j >= 0; --j) {
-               linux_doc_line_break(os, 
-                                    char_line_count, 
-                                    3 + strlen(stack[j]));
-               os << "</" << stack[j] << ">";
+       while (!tag_state.empty()) {
+               os << "</" << tag_name(tag_state.top()) << ">";
+               tag_state.pop();
        }
 
        // resets description flag correctly
-       switch (desc_on){
-       case 1:
+       if (desc_on) {
                // <tag> not closed...
                linux_doc_line_break(os, char_line_count, 6);
                os << "</tag>";
-               break;
-       case 2:
-               // fprintf(file, "</p>");
-               break;
        }
 }
 
@@ -3029,52 +3048,29 @@ void Buffer::LinuxDocError(LyXParagraph * par, int pos,
        par->InsertInset(pos, new_inset);
 }
 
-// This constant defines the maximum number of 
-// environment layouts that can be nesteded.
-// The same applies for command layouts.
-// These values should be more than enough.
-//           José Matos (1999/07/22)
-
-enum { MAX_NEST_LEVEL = 25};
 
 void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
 {
+       ofstream ofs(fname.c_str());
+       if (!ofs) {
+               WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), fname);
+               return;
+       }
+
        LyXParagraph * par = paragraph;
 
        niceFile = nice; // this will be used by Insetincludes.
 
-       string top_element= textclasslist.LatexnameOfClass(params.textclass);
-       // Please use a real stack.
-       string environment_stack[MAX_NEST_LEVEL];
-       string environment_inner[MAX_NEST_LEVEL];
-       // Please use a real stack.
-       string command_stack[MAX_NEST_LEVEL];
-       bool command_flag= false;
-       int command_depth= 0, command_base= 0, cmd_depth= 0;
-
-        string item_name, command_name;
-       string c_depth, c_params, tmps;
-
-       int depth = 0; // paragraph depth
         LyXTextClass const & tclass =
                textclasslist.TextClass(params.textclass);
 
        LaTeXFeatures features(params, tclass.numLayouts());
        validate(features);
-
-       //if (nice)
-       tex_code_break_column = lyxrc.ascii_linelen;
-       //else
-       //tex_code_break_column = 0;
-
-       ofstream ofs(fname.c_str());
-       if (!ofs) {
-               WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), fname);
-               return;
-       }
    
        texrow.reset();
 
+       string top_element= textclasslist.LatexnameOfClass(params.textclass);
+
        if (!only_body) {
                string sgml_includedfiles=features.getIncludedFiles(fname);
 
@@ -3102,8 +3098,20 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
        ofs << "<!-- DocBook file was created by " << LYX_DOCVERSION 
            << "\n  See http://www.lyx.org/ for more information -->\n";
 
+       vector <string> environment_stack(10);
+       vector <string> environment_inner(10);
+       vector <string> command_stack(10);
+
+       bool command_flag= false;
+       int command_depth= 0, command_base= 0, cmd_depth= 0;
+       int depth = 0; // paragraph depth
+
+        string item_name, command_name;
+
        while (par) {
+               string sgmlparam, c_depth, c_params;
                int desc_on = 0; // description mode
+
                LyXLayout const & style =
                        textclasslist.Style(params.textclass,
                                            par->layout);
@@ -3158,24 +3166,19 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                        
                        command_name = style.latexname();
                        
-                       tmps = style.latexparam();
-                       c_params = split(tmps, c_depth,'|');
+                       sgmlparam = style.latexparam();
+                       c_params = split(sgmlparam, c_depth,'|');
                        
                        cmd_depth= lyx::atoi(c_depth);
                        
                        if (command_flag) {
                                if (cmd_depth<command_base) {
-                                       for (int j = command_depth;
-                                           j >= command_base; --j)
-                                               if (!command_stack[j].empty())
-                                                       sgmlCloseTag(ofs, j, command_stack[j]);
+                                       for (int j = command_depth; j >= command_base; --j)
+                                               sgmlCloseTag(ofs, j, command_stack[j]);
                                        command_depth= command_base= cmd_depth;
                                } else if (cmd_depth <= command_depth) {
-                                       for (int j = command_depth;
-                                           j >= cmd_depth; --j)
-
-                                               if (!command_stack[j].empty())
-                                                       sgmlCloseTag(ofs, j, command_stack[j]);
+                                       for (int j = command_depth; j >= cmd_depth; --j)
+                                               sgmlCloseTag(ofs, j, command_stack[j]);
                                        command_depth= cmd_depth;
                                } else
                                        command_depth= cmd_depth;
@@ -3183,6 +3186,8 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                                command_depth = command_base = cmd_depth;
                                command_flag = true;
                        }
+                       if (command_stack.size() == command_depth +1)
+                               command_stack.push_back("");
                        command_stack[command_depth]= command_name;
 
                        // treat label as a special case for
@@ -3214,6 +3219,10 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                        }
 
                        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] = "!-- --";
                                sgmlOpenTag(ofs, depth + command_depth,
@@ -3234,7 +3243,7 @@ void Buffer::makeDocBookFile(string const & fname, bool nice, bool only_body)
                        if (style.latextype == LATEX_ENVIRONMENT) {
                                if (!style.latexparam().empty()) {
                                        if(style.latexparam() == "CDATA")
-                                               ofs << "<![ CDATA [";
+                                               ofs << "<![CDATA[";
                                        else
                                                sgmlOpenTag(ofs, depth + command_depth,
                                                            style.latexparam());
@@ -3354,31 +3363,23 @@ void Buffer::SimpleDocBookOnePar(ostream & os, string & extra,
        LyXLayout const & style = textclasslist.Style(params.textclass,
                                                      par->GetLayout());
 
-       LyXParagraph::size_type main_body;
-       if (style.labeltype != LABEL_MANUAL)
-               main_body = 0;
-       else
-               main_body = par->BeginningOfMainBody();
+       LyXFont font_old = style.labeltype == LABEL_MANUAL ? style.labelfont : style.font;
 
-       // gets paragraph main font
-       LyXFont font1 = main_body > 0 ? style.labelfont : style.font;
-       
        int char_line_count = depth;
        if (!style.free_spacing)
-               for (int j = 0; j < depth; ++j)
-                       os << ' ';
+               os << string(depth,' ');
 
        // parsing main loop
        for (LyXParagraph::size_type i = 0;
             i < par->size(); ++i) {
-               LyXFont font2 = par->getFont(params, i);
+               LyXFont font = par->getFont(params, i);
 
                // handle <emphasis> tag
-               if (font1.emph() != font2.emph() && i) {
-                       if (font2.emph() == LyXFont::ON) {
+               if (font_old.emph() != font.emph()) {
+                       if (font.emph() == LyXFont::ON) {
                                os << "<emphasis>";
                                emph_flag = true;
-                       }else {
+                       }else if(i) {
                                os << "</emphasis>";
                                emph_flag = false;
                        }
@@ -3412,7 +3413,7 @@ void Buffer::SimpleDocBookOnePar(ostream & os, string & extra,
                                else
                                        os << tmp_out;
                        }
-               } else if (font2.latex() == LyXFont::ON) {
+               } else if (font.latex() == LyXFont::ON) {
                        // "TeX"-Mode on ==> SGML-Mode on.
                        if (c != '\0')
                                os << c;
@@ -3435,23 +3436,17 @@ void Buffer::SimpleDocBookOnePar(ostream & os, string & extra,
                                os << sgml_string;
                        }
                }
-               font1 = font2;
+               font_old = font;
        }
 
-       // needed if there is an optional argument but no contents
-       if (main_body > 0 && main_body == par->size()) {
-               font1 = style.font;
-       }
        if (emph_flag) {
                os << "</emphasis>";
        }
        
        // resets description flag correctly
-       switch (desc_on){
-       case 1:
+       if (desc_on == 1) {
                // <term> not closed...
                os << "</term>";
-               break;
        }
        os << '\n';
 }
@@ -3642,7 +3637,8 @@ Buffer::Lists const Buffer::getLists() const
 #ifdef NEW_INSETS
        bool found;
        LyXTextClassList::size_type cap;
-       tie(found, cap) = textclasslist.NumberOfLayout(params.textclass, "Caption");
+       boost::tie(found, cap) = textclasslist
+               .NumberOfLayout(params.textclass, "Caption");
 #endif
 
        while (par) {