From b4f4f487d138f0a1ee797b245d596a254faa2731 Mon Sep 17 00:00:00 2001 From: John Levon Date: Wed, 12 Mar 2003 11:52:23 +0000 Subject: [PATCH] The final parsing patch. Tested on a variety of weird and wonderful things without finding a regression (yet !) :) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6465 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/ChangeLog | 18 ++ src/buffer.C | 439 +++-------------------------------------- src/buffer.h | 12 +- src/bufferparams.C | 3 +- src/bufferparams.h | 4 +- src/factory.C | 123 ++++++++++++ src/factory.h | 7 +- src/insets/ChangeLog | 4 + src/insets/insettext.C | 6 +- src/paragraph_funcs.C | 293 +++++++++++++++++++++++++++ src/paragraph_funcs.h | 4 + src/tabular.C | 7 +- 12 files changed, 477 insertions(+), 443 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 0f0e006a0b..1b619a367d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2003-03-12 John Levon + + * buffer.h: + * buffer.C: move paragraph read into a separate function, + a little renaming to reflect that. + + * bufferparams.h: + * bufferparams.C: remove the author_ids map, not necessary now + + * factory.h: + * factory.C: moved Buffer::readInset to here + + * paragraph_funcs.h: + * paragraph_funcs.C: readParagraph free function moved from + buffer.C + + * tabular.C: name change + 2003-03-12 John Levon * buffer.C: diff --git a/src/buffer.C b/src/buffer.C index 65819731e6..a7399d9fad 100644 --- a/src/buffer.C +++ b/src/buffer.C @@ -47,40 +47,11 @@ #include "mathed/formulamacro.h" #include "mathed/formula.h" -#include "insets/inset.h" #include "insets/inseterror.h" -#include "insets/insethfill.h" -#include "insets/insetlabel.h" -#include "insets/insetref.h" -#include "insets/inseturl.h" -#include "insets/insetnote.h" -#include "insets/insetquotes.h" -#include "insets/insetlatexaccent.h" #include "insets/insetbibitem.h" #include "insets/insetbibtex.h" -#include "insets/insetcite.h" -#include "insets/insetexternal.h" -#include "insets/insetindex.h" #include "insets/insetinclude.h" -#include "insets/insettoc.h" -#include "insets/insetparent.h" -#include "insets/insetspecialchar.h" #include "insets/insettext.h" -#include "insets/insetert.h" -#include "insets/insetgraphics.h" -#include "insets/insetfoot.h" -#include "insets/insetmarginal.h" -#include "insets/insetoptarg.h" -#include "insets/insetminipage.h" -#include "insets/insetfloat.h" -#include "insets/insetwrap.h" -#include "insets/insettabular.h" -#if 0 -#include "insets/insettheorem.h" -#include "insets/insetlist.h" -#endif -#include "insets/insetcaption.h" -#include "insets/insetfloatlist.h" #include "frontends/Dialogs.h" #include "frontends/Alert.h" @@ -344,12 +315,9 @@ bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit) unknown_layouts = 0; int unknown_tokens = 0; - int pos = 0; Paragraph::depth_type depth = 0; bool the_end_read = false; - LyXFont font(LyXFont::ALL_INHERIT, params.language); - if (paragraphs.empty()) { unknown_tokens += readHeader(lex); @@ -370,7 +338,6 @@ bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit) } else { // We are inserting into an existing document users->text->breakParagraph(users, paragraphs); - pos = 0; markDirty(); // We don't want to adopt the parameters from the @@ -396,7 +363,7 @@ bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit) continue; } - unknown_tokens += readToken(lex, paragraphs, pit, token, pos, depth, font); + unknown_tokens += readParagraph(lex, token, paragraphs, pit, depth); } if (unknown_layouts > 0) { @@ -438,282 +405,42 @@ bool Buffer::readBody(LyXLex & lex, ParagraphList::iterator pit) int -Buffer::readToken(LyXLex & lex, ParagraphList & pars, - ParagraphList::iterator & pit, - string const & token, int & pos, - Paragraph::depth_type & depth, - LyXFont & font) +Buffer::readParagraph(LyXLex & lex, string const & token, + ParagraphList & pars, ParagraphList::iterator & pit, + Paragraph::depth_type & depth) { static Change current_change; int unknown = 0; - // The order of the tags tested may seem unnatural, but this - // has been done in order to reduce the number of string - // comparisons needed to recognize a given token. This leads - // on large documents like UserGuide to a reduction of a - // factor 5! (JMarc) - if (token[0] != '\\') { - for (string::const_iterator cit = token.begin(); - cit != token.end(); ++cit) { - pit->insertChar(pos, (*cit), font, current_change); - ++pos; - } - } else if (token == "\\layout") { - // reset the font as we start a new layout and if the font is - // not ALL_INHERIT,document_language then it will be set to the - // right values after this tag (Jug 20020420) - font = LyXFont(LyXFont::ALL_INHERIT, params.language); - - lex.eatLine(); - string layoutname = lex.getString(); + if (token == "\\layout") { + lex.pushToken(token); - LyXTextClass const & tclass = params.getLyXTextClass(); - - if (layoutname.empty()) { - layoutname = tclass.defaultLayoutName(); - } - bool hasLayout = tclass.hasLayout(layoutname); - if (!hasLayout) { - lyxerr << "Layout '" << layoutname << "' does not" - << " exist in textclass '" << tclass.name() - << "'." << endl; - lyxerr << "Trying to use default layout instead." - << endl; - layoutname = tclass.defaultLayoutName(); - } + Paragraph * par = new Paragraph(); + par->params().depth(depth); + if (params.tracking_changes) + par->trackChanges(); + LyXFont f(LyXFont::ALL_INHERIT, params.language); + par->setFont(0, f); -#ifdef USE_CAPTION - // The is the compability reading of layout caption. - // It can be removed in LyX version 1.3.0. (Lgb) - if (compare_ascii_no_case(layoutname, "caption") == 0) { - // We expect that the par we are now working on is - // really inside a InsetText inside a InsetFloat. - // We also know that captions can only be - // one paragraph. (Lgb) - - // We should now read until the next "\layout" - // is reached. - // This is probably not good enough, what if the - // caption is the last par in the document (Lgb) - istream & ist = lex.getStream(); - stringstream ss; - string line; - int begin = 0; - while (true) { - getline(ist, line); - if (prefixIs(line, "\\layout")) { - lex.pushToken(line); - break; - } - if (prefixIs(line, "\\begin_inset")) - ++begin; - if (prefixIs(line, "\\end_inset")) { - if (begin) - --begin; - else { - lex.pushToken(line); - break; - } - } + // FIXME: goddamn InsetTabular makes us pass a Buffer + // not BufferParams + unknown += ::readParagraph(*this, *par, lex); - ss << line << '\n'; - } - // Now we should have the whole layout in ss - // we should now be able to give this to the - // caption inset. - ss << "\\end_inset\n"; - - // This seems like a bug in stringstream. - // We really should be able to use ss - // directly. (Lgb) - istringstream is(ss.str()); - LyXLex tmplex(0, 0); - tmplex.setStream(is); - Inset * inset = new InsetCaption; - inset->Read(this, tmplex); - pit->InsertInset(pos, inset, font); - ++pos; - } else { -#endif - Paragraph * par = new Paragraph(); - if (params.tracking_changes) - par->trackChanges(); - pos = 0; - par->layout(params.getLyXTextClass()[layoutname]); - // Test whether the layout is obsolete. - LyXLayout_ptr const & layout = par->layout(); - if (!layout->obsoleted_by().empty()) - par->layout(params.getLyXTextClass()[layout->obsoleted_by()]); - par->params().depth(depth); - - par->params().read(lex); - - // insert after - if (pit != pars.end()) - ++pit; - pit = pars.insert(pit, par); -#if USE_CAPTION - } -#endif - - } else if (token == "\\end_inset") { - lyxerr << "Solitary \\end_inset in line " << lex.getLineNo() << "\n" - << "Missing \\begin_inset?.\n"; - // Simply ignore this. The insets do not have - // to read this. - // But insets should read it, it is a part of - // the inset isn't it? Lgb. - } else if (token == "\\begin_inset") { - readInset(lex, pit, pos, font, current_change); - } else if (token == "\\family") { - lex.next(); - font.setLyXFamily(lex.getString()); - } else if (token == "\\series") { - lex.next(); - font.setLyXSeries(lex.getString()); - } else if (token == "\\shape") { - lex.next(); - font.setLyXShape(lex.getString()); - } else if (token == "\\size") { - lex.next(); - font.setLyXSize(lex.getString()); - } else if (token == "\\lang") { - lex.next(); - string const tok = lex.getString(); - Language const * lang = languages.getLanguage(tok); - if (lang) { - font.setLanguage(lang); - } else { - font.setLanguage(params.language); - lex.printError("Unknown language `$$Token'"); - } - } else if (token == "\\numeric") { - lex.next(); - font.setNumber(font.setLyXMisc(lex.getString())); - } else if (token == "\\emph") { - lex.next(); - font.setEmph(font.setLyXMisc(lex.getString())); - } else if (token == "\\bar") { - lex.next(); - string const tok = lex.getString(); - // This is dirty, but gone with LyX3. (Asger) - if (tok == "under") - font.setUnderbar(LyXFont::ON); - else if (tok == "no") - font.setUnderbar(LyXFont::OFF); - else if (tok == "default") - font.setUnderbar(LyXFont::INHERIT); - else - lex.printError("Unknown bar font flag " - "`$$Token'"); - } else if (token == "\\noun") { - lex.next(); - font.setNoun(font.setLyXMisc(lex.getString())); - } else if (token == "\\color") { - lex.next(); - font.setLyXColor(lex.getString()); - } else if (token == "\\SpecialChar") { - LyXLayout_ptr const & layout = pit->layout(); - - // Insets don't make sense in a free-spacing context! ---Kayvan - if (layout->free_spacing || pit->isFreeSpacing()) { - if (lex.isOK()) { - lex.next(); - string const next_token = lex.getString(); - if (next_token == "\\-") { - pit->insertChar(pos, '-', font, current_change); - } else if (next_token == "~") { - pit->insertChar(pos, ' ', font, current_change); - } else { - lex.printError("Token `$$Token' " - "is in free space " - "paragraph layout!"); - --pos; - } - } - } else { - Inset * inset = new InsetSpecialChar; - inset->read(this, lex); - pit->insertInset(pos, inset, font, current_change); - } - ++pos; - } else if (token == "\\i") { - Inset * inset = new InsetLatexAccent; - inset->read(this, lex); - pit->insertInset(pos, inset, font, current_change); - ++pos; - } else if (token == "\\backslash") { - pit->insertChar(pos, '\\', font, current_change); - ++pos; + // insert after + if (pit != pars.end()) + ++pit; + pit = pars.insert(pit, par); } else if (token == "\\begin_deeper") { ++depth; } else if (token == "\\end_deeper") { if (!depth) { - lex.printError("\\end_deeper: " - "depth is already null"); - } - else + lex.printError("\\end_deeper: " "depth is already null"); + } else { --depth; - // do not delete this token, it is still needed! - } else if (token == "\\newline") { - pit->insertChar(pos, Paragraph::META_NEWLINE, font, current_change); - ++pos; - } else if (token == "\\LyXTable") { - Inset * inset = new InsetTabular(*this); - inset->read(this, lex); - pit->insertInset(pos, inset, font, current_change); - ++pos; - } else if (token == "\\bibitem") { // ale970302 - InsetCommandParams p("bibitem", "dummy"); - InsetBibitem * inset = new InsetBibitem(p); - inset->read(this, lex); - pit->insertInset(pos, inset, font, current_change); - ++pos; - } else if (token == "\\hfill") { - pit->insertInset(pos, new InsetHFill(), - LyXFont(LyXFont::ALL_INHERIT, params.language)); - ++pos; - } else if (token == "\\change_unchanged") { - // Hack ! Needed for empty paragraphs :/ - if (!pos) - pit->cleanChanges(); - current_change = Change(Change::UNCHANGED); - } else if (token == "\\change_inserted") { - lex.nextToken(); - istringstream istr(lex.getString()); - int aid; - lyx::time_type ct; - istr >> aid; - istr >> ct; - current_change = Change(Change::INSERTED, params.author_ids[aid], ct); - } else if (token == "\\change_deleted") { - lex.nextToken(); - istringstream istr(lex.getString()); - int aid; - lyx::time_type ct; - istr >> aid; - istr >> ct; - current_change = Change(Change::DELETED, params.author_ids[aid], ct); + } } else { - // This should be insurance for the future: (Asger) ++unknown; - lex.eatLine(); -#if USE_BOOST_FORMAT - boost::format fmt(_("Unknown token: %1$s %2$s\n")); - fmt % token % lex.text(); - string const s = fmt.str(); -#else - string const s = _("Unknown token: ") + token - + ' ' + lex.text() + '\n'; -#endif - // we can do this here this way because we're actually reading - // the buffer and don't care about LyXText right now. - InsetError * new_inset = new InsetError(s); - pit->insertInset(pos, new_inset, LyXFont(LyXFont::ALL_INHERIT, - params.language)); - } - return unknown; } @@ -777,128 +504,6 @@ void Buffer::insertStringAsLines(Paragraph *& par, pos_type & pos, } -void Buffer::readInset(LyXLex & lex, ParagraphList::iterator pit, - int & pos, LyXFont & font, Change current_change) -{ - // consistency check - if (lex.getString() != "\\begin_inset") { - lyxerr << "Buffer::readInset: Consistency check failed." - << endl; - } - - Inset * inset = 0; - - lex.next(); - string const tmptok = lex.getString(); - - // test the different insets - if (tmptok == "LatexCommand") { - InsetCommandParams inscmd; - inscmd.read(lex); - - string const cmdName = inscmd.getCmdName(); - - // This strange command allows LyX to recognize "natbib" style - // citations: citet, citep, Citet etc. - if (compare_ascii_no_case(cmdName.substr(0,4), "cite") == 0) { - inset = new InsetCitation(inscmd); - } else if (cmdName == "bibitem") { - lex.printError("Wrong place for bibitem"); - inset = new InsetBibitem(inscmd); - } else if (cmdName == "BibTeX") { - inset = new InsetBibtex(inscmd); - } else if (cmdName == "index") { - inset = new InsetIndex(inscmd); - } else if (cmdName == "include") { - inset = new InsetInclude(inscmd, *this); - } else if (cmdName == "label") { - inset = new InsetLabel(inscmd); - } else if (cmdName == "url" - || cmdName == "htmlurl") { - inset = new InsetUrl(inscmd); - } else if (cmdName == "ref" - || cmdName == "pageref" - || cmdName == "vref" - || cmdName == "vpageref" - || cmdName == "prettyref") { - if (!inscmd.getOptions().empty() - || !inscmd.getContents().empty()) { - inset = new InsetRef(inscmd, *this); - } - } else if (cmdName == "tableofcontents") { - inset = new InsetTOC(inscmd); - } else if (cmdName == "listofalgorithms") { - inset = new InsetFloatList("algorithm"); - } else if (cmdName == "listoffigures") { - inset = new InsetFloatList("figure"); - } else if (cmdName == "listoftables") { - inset = new InsetFloatList("table"); - } else if (cmdName == "printindex") { - inset = new InsetPrintIndex(inscmd); - } else if (cmdName == "lyxparent") { - inset = new InsetParent(inscmd, *this); - } - } else { - if (tmptok == "Quotes") { - inset = new InsetQuotes; - } else if (tmptok == "External") { - inset = new InsetExternal; - } else if (tmptok == "FormulaMacro") { - inset = new InsetFormulaMacro; - } else if (tmptok == "Formula") { - inset = new InsetFormula; - } else if (tmptok == "Graphics") { - inset = new InsetGraphics; - } else if (tmptok == "Note") { - inset = new InsetNote(params); - } else if (tmptok == "Include") { - InsetCommandParams p("Include"); - inset = new InsetInclude(p, *this); - } else if (tmptok == "ERT") { - inset = new InsetERT(params); - } else if (tmptok == "Tabular") { - inset = new InsetTabular(*this); - } else if (tmptok == "Text") { - inset = new InsetText(params); - } else if (tmptok == "Foot") { - inset = new InsetFoot(params); - } else if (tmptok == "Marginal") { - inset = new InsetMarginal(params); - } else if (tmptok == "OptArg") { - inset = new InsetOptArg(params); - } else if (tmptok == "Minipage") { - inset = new InsetMinipage(params); - } else if (tmptok == "Float") { - lex.next(); - string tmptok = lex.getString(); - inset = new InsetFloat(params, tmptok); - } else if (tmptok == "Wrap") { - lex.next(); - string tmptok = lex.getString(); - inset = new InsetWrap(params, tmptok); -#if 0 - } else if (tmptok == "List") { - inset = new InsetList; - } else if (tmptok == "Theorem") { - inset = new InsetList; -#endif - } else if (tmptok == "Caption") { - inset = new InsetCaption(params); - } else if (tmptok == "FloatList") { - inset = new InsetFloatList; - } - - if (inset) - inset->read(this, lex); - } - - if (inset) { - pit->insertInset(pos, inset, font, current_change); - ++pos; - } -} - - bool Buffer::readFile(LyXLex & lex, string const & filename) { return readFile(lex, filename, paragraphs.begin()); diff --git a/src/buffer.h b/src/buffer.h index 46cd4b0afb..9f749f4969 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -112,11 +112,9 @@ public: bool readBody(LyXLex &, ParagraphList::iterator pit); /// This parses a single token - int readToken(LyXLex &, ParagraphList & pars, - ParagraphList::iterator & pit, - string const & token, int & pos, - Paragraph::depth_type & depth, - LyXFont &); + int readParagraph(LyXLex &, string const & token, + ParagraphList & pars, ParagraphList::iterator & pit, + Paragraph::depth_type & depth); /// void insertStringAsLines(Paragraph *&, lyx::pos_type &, @@ -124,10 +122,6 @@ public: /// Paragraph * getParFromID(int id) const; -private: - /// Parse a single inset. - void readInset(LyXLex &, ParagraphList::iterator pit, int & pos, LyXFont &, Change current_change); - public: /** Save file. Takes care of auto-save files and backup file if requested. diff --git a/src/bufferparams.C b/src/bufferparams.C index 8354e7d23f..3fc1794eb1 100644 --- a/src/bufferparams.C +++ b/src/bufferparams.C @@ -189,8 +189,7 @@ string const BufferParams::readToken(LyXLex & lex, string const & token) istringstream ss(lex.getString()); Author a; ss >> a; - int aid(authorlist.record(a)); - author_ids.push_back(aid); + authorlist.record(a); } else if (token == "\\paperorientation") { int tmpret = lex.findToken(string_orientation); if (tmpret == -1) diff --git a/src/bufferparams.h b/src/bufferparams.h index 370b160179..8be76a23d0 100644 --- a/src/bufferparams.h +++ b/src/bufferparams.h @@ -231,10 +231,8 @@ public: bool tracking_changes; /// Time ago we agreed that this was a buffer property [ale990407] string parentname; -private: - /// mapping of author IDs - std::vector author_ids; +private: /// the author list AuthorList authorlist; diff --git a/src/factory.C b/src/factory.C index f8fb8bf522..24cd050bfd 100644 --- a/src/factory.C +++ b/src/factory.C @@ -17,6 +17,7 @@ #include "debug.h" #include "BufferView.h" #include "lyxtext.h" +#include "lyxlex.h" #include "insets/insetbibitem.h" #include "insets/insetbibtex.h" @@ -25,6 +26,7 @@ #include "insets/insetert.h" #include "insets/insetexternal.h" #include "insets/insetfloat.h" +#include "insets/insetfloatlist.h" #include "insets/insetfoot.h" #include "insets/insetgraphics.h" #include "insets/insethfill.h" @@ -42,9 +44,12 @@ #include "insets/insettoc.h" #include "insets/inseturl.h" #include "insets/insetwrap.h" +#include "mathed/formulamacro.h" +#include "mathed/formula.h" #include "frontends/Dialogs.h" #include "frontends/LyXView.h" +#include "support/lstrings.h" #include @@ -244,3 +249,121 @@ Inset * createInset(FuncRequest const & cmd) return 0; } + + +Inset * readInset(LyXLex & lex, Buffer const & buf) +{ + // consistency check + if (lex.getString() != "\\begin_inset") { + lyxerr << "Buffer::readInset: Consistency check failed." + << endl; + } + + Inset * inset = 0; + + lex.next(); + string const tmptok = lex.getString(); + + // test the different insets + if (tmptok == "LatexCommand") { + InsetCommandParams inscmd; + inscmd.read(lex); + + string const cmdName = inscmd.getCmdName(); + + // This strange command allows LyX to recognize "natbib" style + // citations: citet, citep, Citet etc. + if (compare_ascii_no_case(cmdName.substr(0,4), "cite") == 0) { + inset = new InsetCitation(inscmd); + } else if (cmdName == "bibitem") { + lex.printError("Wrong place for bibitem"); + inset = new InsetBibitem(inscmd); + } else if (cmdName == "BibTeX") { + inset = new InsetBibtex(inscmd); + } else if (cmdName == "index") { + inset = new InsetIndex(inscmd); + } else if (cmdName == "include") { + inset = new InsetInclude(inscmd, buf); + } else if (cmdName == "label") { + inset = new InsetLabel(inscmd); + } else if (cmdName == "url" + || cmdName == "htmlurl") { + inset = new InsetUrl(inscmd); + } else if (cmdName == "ref" + || cmdName == "pageref" + || cmdName == "vref" + || cmdName == "vpageref" + || cmdName == "prettyref") { + if (!inscmd.getOptions().empty() + || !inscmd.getContents().empty()) { + inset = new InsetRef(inscmd, buf); + } + } else if (cmdName == "tableofcontents") { + inset = new InsetTOC(inscmd); + } else if (cmdName == "listofalgorithms") { + inset = new InsetFloatList("algorithm"); + } else if (cmdName == "listoffigures") { + inset = new InsetFloatList("figure"); + } else if (cmdName == "listoftables") { + inset = new InsetFloatList("table"); + } else if (cmdName == "printindex") { + inset = new InsetPrintIndex(inscmd); + } else if (cmdName == "lyxparent") { + inset = new InsetParent(inscmd, buf); + } + } else { + if (tmptok == "Quotes") { + inset = new InsetQuotes; + } else if (tmptok == "External") { + inset = new InsetExternal; + } else if (tmptok == "FormulaMacro") { + inset = new InsetFormulaMacro; + } else if (tmptok == "Formula") { + inset = new InsetFormula; + } else if (tmptok == "Graphics") { + inset = new InsetGraphics; + } else if (tmptok == "Note") { + inset = new InsetNote(buf.params); + } else if (tmptok == "Include") { + InsetCommandParams p("Include"); + inset = new InsetInclude(p, buf); + } else if (tmptok == "ERT") { + inset = new InsetERT(buf.params); + } else if (tmptok == "Tabular") { + inset = new InsetTabular(buf); + } else if (tmptok == "Text") { + inset = new InsetText(buf.params); + } else if (tmptok == "Foot") { + inset = new InsetFoot(buf.params); + } else if (tmptok == "Marginal") { + inset = new InsetMarginal(buf.params); + } else if (tmptok == "OptArg") { + inset = new InsetOptArg(buf.params); + } else if (tmptok == "Minipage") { + inset = new InsetMinipage(buf.params); + } else if (tmptok == "Float") { + lex.next(); + string tmptok = lex.getString(); + inset = new InsetFloat(buf.params, tmptok); + } else if (tmptok == "Wrap") { + lex.next(); + string tmptok = lex.getString(); + inset = new InsetWrap(buf.params, tmptok); +#if 0 + } else if (tmptok == "List") { + inset = new InsetList; + } else if (tmptok == "Theorem") { + inset = new InsetList; +#endif + } else if (tmptok == "Caption") { + inset = new InsetCaption(buf.params); + } else if (tmptok == "FloatList") { + inset = new InsetFloatList; + } + + if (inset) + inset->read(&buf, lex); + } + + return inset; +} diff --git a/src/factory.h b/src/factory.h index 1c25480fdc..772f28b022 100644 --- a/src/factory.h +++ b/src/factory.h @@ -14,8 +14,13 @@ class Inset; class FuncRequest; +class LyXLex; +class Buffer; /// creates inset according to 'cmd' Inset * createInset(FuncRequest const & cmd); -#endif +/// read inset from a file +Inset * readInset(LyXLex & lex, Buffer const & buf); + +#endif // FACTORY_H diff --git a/src/insets/ChangeLog b/src/insets/ChangeLog index e4e72e100c..c6db5cab60 100644 --- a/src/insets/ChangeLog +++ b/src/insets/ChangeLog @@ -1,3 +1,7 @@ +2003-03-12 John Levon + + * insettext.C: readToken became readParagraph + 2003-03-12 John Levon * insettext.C: use parlist iterator for reading contents diff --git a/src/insets/insettext.C b/src/insets/insettext.C index 43d6badf46..1f1a1e2440 100644 --- a/src/insets/insettext.C +++ b/src/insets/insettext.C @@ -261,9 +261,7 @@ void InsetText::writeParagraphData(Buffer const * buf, ostream & os) const void InsetText::read(Buffer const * buf, LyXLex & lex) { string token; - int pos = 0; Paragraph::depth_type depth = 0; - LyXFont font(LyXFont::ALL_INHERIT); clear(false); @@ -289,9 +287,7 @@ void InsetText::read(Buffer const * buf, LyXLex & lex) } // FIXME: ugly. - - const_cast(buf)->readToken(lex, paragraphs, pit, - token, pos, depth, font); + const_cast(buf)->readParagraph(lex, token, paragraphs, pit, depth); } pit = paragraphs.begin(); diff --git a/src/paragraph_funcs.C b/src/paragraph_funcs.C index a7b5c4546b..04081b6195 100644 --- a/src/paragraph_funcs.C +++ b/src/paragraph_funcs.C @@ -16,11 +16,22 @@ #include "ParagraphParameters.h" #include "lyxtextclasslist.h" #include "debug.h" +#include "gettext.h" #include "language.h" #include "encoding.h" #include "lyxrc.h" +#include "lyxlex.h" +#include "BoostFormat.h" +#include "factory.h" #include "support/lstrings.h" #include "insets/insetoptarg.h" +#include "insets/insetcommandparams.h" +#include "insets/insetbibitem.h" +#include "insets/insetspecialchar.h" +#include "insets/insetlatexaccent.h" +#include "insets/insettabular.h" +#include "insets/insethfill.h" +#include "insets/inseterror.h" extern string bibitemWidest(Buffer const *); @@ -714,3 +725,285 @@ void latexParagraphs(Buffer const * buf, texrow.newline(); } } + + +namespace { + +int readParToken(Buffer & buf, Paragraph & par, LyXLex & lex, string const & token) +{ + static LyXFont font; + static Change change; + + BufferParams const & bp = buf.params; + + if (token[0] != '\\') { + string::const_iterator cit = token.begin(); + for (; cit != token.end(); ++cit) { + par.insertChar(par.size(), (*cit), font, change); + } + } else if (token == "\\layout") { + lex.eatLine(); + string layoutname = lex.getString(); + + font = LyXFont(LyXFont::ALL_INHERIT, bp.language); + change = Change(); + + LyXTextClass const & tclass = bp.getLyXTextClass(); + + if (layoutname.empty()) { + layoutname = tclass.defaultLayoutName(); + } + + bool hasLayout = tclass.hasLayout(layoutname); + + if (!hasLayout) { + lyxerr << "Layout '" << layoutname << "' does not" + << " exist in textclass '" << tclass.name() + << "'." << endl; + lyxerr << "Trying to use default layout instead." + << endl; + layoutname = tclass.defaultLayoutName(); + } + +#ifdef USE_CAPTION + // The is the compability reading of layout caption. + if (compare_ascii_no_case(layoutname, "caption") == 0) { + // We expect that the par we are now working on is + // really inside a InsetText inside a InsetFloat. + // We also know that captions can only be + // one paragraph. (Lgb) + + // We should now read until the next "\layout" + // is reached. + // This is probably not good enough, what if the + // caption is the last par in the document (Lgb) + istream & ist = lex.getStream(); + stringstream ss; + string line; + int begin = 0; + while (true) { + getline(ist, line); + if (prefixIs(line, "\\layout")) { + lex.pushToken(line); + break; + } + if (prefixIs(line, "\\begin_inset")) + ++begin; + if (prefixIs(line, "\\end_inset")) { + if (begin) + --begin; + else { + lex.pushToken(line); + break; + } + } + + ss << line << '\n'; + } + + // Now we should have the whole layout in ss + // we should now be able to give this to the + // caption inset. + ss << "\\end_inset\n"; + + // This seems like a bug in stringstream. + // We really should be able to use ss + // directly. (Lgb) + istringstream is(ss.str()); + LyXLex tmplex(0, 0); + tmplex.setStream(is); + Inset * inset = new InsetCaption; + inset->Read(this, tmplex); + par.insertInset(pos, inset, font); + ++pos; + } else { +#endif + par.layout(bp.getLyXTextClass()[layoutname]); + + // Test whether the layout is obsolete. + LyXLayout_ptr const & layout = par.layout(); + if (!layout->obsoleted_by().empty()) + par.layout(bp.getLyXTextClass()[layout->obsoleted_by()]); + + par.params().read(lex); +#if USE_CAPTION + } +#endif + + } else if (token == "\\end_inset") { + lyxerr << "Solitary \\end_inset in line " << lex.getLineNo() << "\n" + << "Missing \\begin_inset?.\n"; + // Simply ignore this. The insets do not have + // to read this. + // But insets should read it, it is a part of + // the inset isn't it? Lgb. + } else if (token == "\\begin_inset") { + Inset * i = readInset(lex, buf); + par.insertInset(par.size(), i, font, change); + } else if (token == "\\family") { + lex.next(); + font.setLyXFamily(lex.getString()); + } else if (token == "\\series") { + lex.next(); + font.setLyXSeries(lex.getString()); + } else if (token == "\\shape") { + lex.next(); + font.setLyXShape(lex.getString()); + } else if (token == "\\size") { + lex.next(); + font.setLyXSize(lex.getString()); + } else if (token == "\\lang") { + lex.next(); + string const tok = lex.getString(); + Language const * lang = languages.getLanguage(tok); + if (lang) { + font.setLanguage(lang); + } else { + font.setLanguage(bp.language); + lex.printError("Unknown language `$$Token'"); + } + } else if (token == "\\numeric") { + lex.next(); + font.setNumber(font.setLyXMisc(lex.getString())); + } else if (token == "\\emph") { + lex.next(); + font.setEmph(font.setLyXMisc(lex.getString())); + } else if (token == "\\bar") { + lex.next(); + string const tok = lex.getString(); + + if (tok == "under") + font.setUnderbar(LyXFont::ON); + else if (tok == "no") + font.setUnderbar(LyXFont::OFF); + else if (tok == "default") + font.setUnderbar(LyXFont::INHERIT); + else + lex.printError("Unknown bar font flag " + "`$$Token'"); + } else if (token == "\\noun") { + lex.next(); + font.setNoun(font.setLyXMisc(lex.getString())); + } else if (token == "\\color") { + lex.next(); + font.setLyXColor(lex.getString()); + } else if (token == "\\SpecialChar") { + LyXLayout_ptr const & layout = par.layout(); + + // Insets don't make sense in a free-spacing context! ---Kayvan + if (layout->free_spacing || par.isFreeSpacing()) { + if (lex.isOK()) { + lex.next(); + string const next_token = lex.getString(); + if (next_token == "\\-") { + par.insertChar(par.size(), '-', font, change); + } else if (next_token == "~") { + par.insertChar(par.size(), ' ', font, change); + } else { + lex.printError("Token `$$Token' " + "is in free space " + "paragraph layout!"); + } + } + } else { + Inset * inset = new InsetSpecialChar; + inset->read(&buf, lex); + par.insertInset(par.size(), inset, font, change); + } + } else if (token == "\\i") { + Inset * inset = new InsetLatexAccent; + inset->read(&buf, lex); + par.insertInset(par.size(), inset, font, change); + } else if (token == "\\backslash") { + par.insertChar(par.size(), '\\', font, change); + // do not delete this token, it is still needed! + } else if (token == "\\newline") { + par.insertChar(par.size(), Paragraph::META_NEWLINE, font, change); + } else if (token == "\\LyXTable") { + Inset * inset = new InsetTabular(buf); + inset->read(&buf, lex); + par.insertInset(par.size(), inset, font, change); + } else if (token == "\\bibitem") { + InsetCommandParams p("bibitem", "dummy"); + InsetBibitem * inset = new InsetBibitem(p); + inset->read(&buf, lex); + par.insertInset(par.size(), inset, font, change); + } else if (token == "\\hfill") { + par.insertInset(par.size(), new InsetHFill(), font, change); + } else if (token == "\\change_unchanged") { + // Hack ! Needed for empty paragraphs :/ + // FIXME: is it still ?? + if (!par.size()) + par.cleanChanges(); + change = Change(Change::UNCHANGED); + } else if (token == "\\change_inserted") { + lex.nextToken(); + istringstream istr(lex.getString()); + int aid; + lyx::time_type ct; + istr >> aid; + istr >> ct; + change = Change(Change::INSERTED, aid, ct); + } else if (token == "\\change_deleted") { + lex.nextToken(); + istringstream istr(lex.getString()); + int aid; + lyx::time_type ct; + istr >> aid; + istr >> ct; + change = Change(Change::DELETED, aid, ct); + } else { + lex.eatLine(); +#if USE_BOOST_FORMAT + boost::format fmt(_("Unknown token: %1$s %2$s\n")); + fmt % token % lex.text(); + string const s = fmt.str(); +#else + string const s = _("Unknown token: ") + token + + ' ' + lex.text() + '\n'; +#endif + // we can do this here this way because we're actually reading + // the buffer and don't care about LyXText right now. + InsetError * inset = new InsetError(s); + par.insertInset(par.size(), inset, font); + return 1; + } + return 0; +} + +} + + +int readParagraph(Buffer & buf, Paragraph & par, LyXLex & lex) +{ + int unknown = 0; + + lex.nextToken(); + string token = lex.getString(); + + while (lex.isOK()) { + + unknown += readParToken(buf, par, lex, token); + + lex.nextToken(); + token = lex.getString(); + + if (token.empty()) + continue; + + lyxerr[Debug::PARSER] << "Handling paragraph token: `" + << token << '\'' << endl; + + // reached the next paragraph. FIXME: really we should + // change the file format to indicate the end of a par + // clearly, but for now, this hack will do + if (token == "\\layout" || token == "\\the_end" + || token == "\\end_inset" || token == "\\begin_deeper" + || token == "\\end_deeper") { + lex.pushToken(token); + break; + } + } + + return unknown; +} diff --git a/src/paragraph_funcs.h b/src/paragraph_funcs.h index 23c8cdd78f..6430e3de11 100644 --- a/src/paragraph_funcs.h +++ b/src/paragraph_funcs.h @@ -19,6 +19,7 @@ class Buffer; class BufferParams; class Paragraph; class TexRow; +class LyXLex; /// void breakParagraph(BufferParams const & bparams, @@ -86,4 +87,7 @@ void latexParagraphs(Buffer const * buf, TexRow & texrow, bool moving_arg = false); +/// read a paragraph from a .lyx file. Returns number of unrecognised tokens +int readParagraph(Buffer & buf, Paragraph & par, LyXLex & lex); + #endif // PARAGRAPH_FUNCS_H diff --git a/src/tabular.C b/src/tabular.C index 78234ba3d8..0562d9c06f 100644 --- a/src/tabular.C +++ b/src/tabular.C @@ -1447,10 +1447,7 @@ void LyXTabular::OldFormatRead(BufferParams const & bp, set_row_column_number_info(true); string tmptok; - int pos = 0; Paragraph::depth_type depth = 0; - LyXFont font(LyXFont::ALL_INHERIT); - font.setLanguage(owner_->bufferOwner()->getLanguage()); ParagraphList parlist; ParagraphList::iterator pit = parlist.begin(); @@ -1474,9 +1471,7 @@ void LyXTabular::OldFormatRead(BufferParams const & bp, break; } - owner_->bufferOwner()->readToken(lex, parlist, pit, - token, pos, depth, font); - + owner_->bufferOwner()->readParagraph(lex, token, parlist, pit, depth); } Paragraph * par = &(*parlist.begin()); -- 2.39.5