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
This commit is contained in:
John Levon 2003-03-12 11:52:23 +00:00
parent d5abf45c1d
commit b4f4f487d1
12 changed files with 477 additions and 443 deletions

View File

@ -1,3 +1,21 @@
2003-03-12 John Levon <levon@movementarian.org>
* 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 <levon@movementarian.org>
* buffer.C:

View File

@ -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);
if (token == "\\layout") {
lex.pushToken(token);
lex.eatLine();
string layoutname = lex.getString();
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);
LyXTextClass const & tclass = params.getLyXTextClass();
// FIXME: goddamn InsetTabular makes us pass a Buffer
// not BufferParams
unknown += ::readParagraph(*this, *par, lex);
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.
// 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;
}
}
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());

View File

@ -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.

View File

@ -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)

View File

@ -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<int> author_ids;
private:
/// the author list
AuthorList authorlist;

View File

@ -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 <cstdio>
@ -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;
}

View File

@ -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

View File

@ -1,3 +1,7 @@
2003-03-12 John Levon <levon@movementarian.org>
* insettext.C: readToken became readParagraph
2003-03-12 John Levon <levon@movementarian.org>
* insettext.C: use parlist iterator for reading contents

View File

@ -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<Buffer*>(buf)->readToken(lex, paragraphs, pit,
token, pos, depth, font);
const_cast<Buffer*>(buf)->readParagraph(lex, token, paragraphs, pit, depth);
}
pit = paragraphs.begin();

View File

@ -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;
}

View File

@ -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

View File

@ -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());