From 990069f5463dd0b57e0ea1f792b15a320ed8358a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Andr=C3=A9=20P=C3=B6nitz?= Date: Wed, 31 Jul 2002 17:26:14 +0000 Subject: [PATCH] a step towards world domination^H^H^H aehm... move things from the parbox inset to an abstract base class 'MathTextInset' and have a shot on implementing an ERT inset on top of that. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4819 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/mathed/Makefile.am | 4 + src/mathed/formulabase.C | 26 +++-- src/mathed/math_cursor.C | 6 + src/mathed/math_ertinset.C | 42 +++++++ src/mathed/math_ertinset.h | 26 +++++ src/mathed/math_factory.C | 66 +++++------ src/mathed/math_gridinset.C | 4 +- src/mathed/math_gridinset.h | 12 +- src/mathed/math_mathmlstream.C | 6 +- src/mathed/math_metricsinfo.C | 1 - src/mathed/math_parboxinset.C | 196 +-------------------------------- src/mathed/math_parboxinset.h | 21 +--- src/mathed/math_parinset.C | 6 - src/mathed/math_parinset.h | 2 +- src/mathed/math_parser.C | 45 ++++---- src/mathed/math_scriptinset.C | 8 +- src/mathed/math_support.C | 1 + src/mathed/math_textinset.C | 165 +++++++++++++++++++++++++++ src/mathed/math_textinset.h | 32 ++++++ src/mathed/math_xdata.C | 81 +++----------- src/mathed/math_xdata.h | 22 ---- 21 files changed, 392 insertions(+), 380 deletions(-) create mode 100644 src/mathed/math_ertinset.C create mode 100644 src/mathed/math_ertinset.h create mode 100644 src/mathed/math_textinset.C create mode 100644 src/mathed/math_textinset.h diff --git a/src/mathed/Makefile.am b/src/mathed/Makefile.am index b8ecffc96f..9521651ad8 100644 --- a/src/mathed/Makefile.am +++ b/src/mathed/Makefile.am @@ -51,6 +51,8 @@ libmathed_la_SOURCES = \ math_dotsinset.h \ math_envinset.C \ math_envinset.h \ + math_ertinset.C \ + math_ertinset.h \ math_extern.C \ math_extern.h \ math_exfuncinset.C \ @@ -134,6 +136,8 @@ libmathed_la_SOURCES = \ math_support.h \ math_symbolinset.C \ math_symbolinset.h \ + math_textinset.C \ + math_textinset.h \ math_unknowninset.C \ math_unknowninset.h \ math_undersetinset.C \ diff --git a/src/mathed/formulabase.C b/src/mathed/formulabase.C index 49583a8153..1fc4ff5a75 100644 --- a/src/mathed/formulabase.C +++ b/src/mathed/formulabase.C @@ -208,9 +208,11 @@ void InsetFormulaBase::insetUnlock(BufferView * bv) } -void InsetFormulaBase::getCursorPos(BufferView * bv, int & x, int & y) const +void InsetFormulaBase::getCursorPos(BufferView *, int & x, int & y) const { - metrics(bv); + // calling metrics here destroys the cached xo,yo positions e.g. in + // MathParboxinset. And it would be too expensive anyway... + //metrics(bv); mathcursor->getPos(x, y); //x -= xo_; y -= yo_; @@ -403,6 +405,7 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, if (!mathcursor) return UNDISPATCHED; + string argument = arg; RESULT result = DISPATCHED; bool sel = false; @@ -696,11 +699,6 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, result = UNDISPATCHED; break; - case LFUN_BREAKPARAGRAPH: - case LFUN_BREAKPARAGRAPHKEEPLAYOUT: - //lyxerr << "LFUN ignored\n"; - break; - case LFUN_INSET_ERT: // interpret this as if a backslash was typed bv->lockedInsetStoreUndo(Undo::EDIT); @@ -708,15 +706,21 @@ InsetFormulaBase::localDispatch(BufferView * bv, kb_action action, updateLocal(bv, true); break; + case LFUN_BREAKPARAGRAPH: + case LFUN_BREAKPARAGRAPHKEEPLAYOUT: + case LFUN_BREAKPARAGRAPH_SKIP: + argument = "\n"; + // fall through + case -1: case LFUN_INSERT_MATH: case LFUN_SELFINSERT: - if (!arg.empty()) { + if (!argument.empty()) { bv->lockedInsetStoreUndo(Undo::EDIT); - if (arg.size() == 1) - result = mathcursor->interpret(arg[0]) ? DISPATCHED : FINISHED_RIGHT; + if (argument.size() == 1) + result = mathcursor->interpret(argument[0]) ? DISPATCHED : FINISHED_RIGHT; else - result = mathcursor->interpret(arg) ? DISPATCHED : FINISHED_RIGHT; + result = mathcursor->interpret(argument) ? DISPATCHED : FINISHED_RIGHT; updateLocal(bv, true); } break; diff --git a/src/mathed/math_cursor.C b/src/mathed/math_cursor.C index 7322a4e4b3..aebf2fa504 100644 --- a/src/mathed/math_cursor.C +++ b/src/mathed/math_cursor.C @@ -1399,6 +1399,12 @@ bool MathCursor::interpret(char c) return true; } + if (c == '\n') { + if (currentMode() == MathInset::TEXT_MODE) + insert(c); + return true; + } + if (c == ' ') { if (currentMode() == MathInset::TEXT_MODE) { // insert spaces in text mode, diff --git a/src/mathed/math_ertinset.C b/src/mathed/math_ertinset.C new file mode 100644 index 0000000000..2ee1347fc0 --- /dev/null +++ b/src/mathed/math_ertinset.C @@ -0,0 +1,42 @@ + +#include "math_ertinset.h" +#include "math_mathmlstream.h" + + +MathInset * MathErtInset::clone() const +{ + return new MathErtInset(*this); +} + + +void MathErtInset::metrics(MathMetricsInfo & mi) const +{ + MathFontSetChanger dummy(mi.base, "lyxert"); + MathTextInset::metrics(mi); + cache_.colinfo_[0].align_ = 'l'; + metricsMarkers2(); +} + + +void MathErtInset::draw(MathPainterInfo & pi, int x, int y) const +{ + MathFontSetChanger dummy(pi.base, "lyxert"); + MathTextInset::draw(pi, x + 1, y); + drawMarkers2(pi, x, y); +} + + +void MathErtInset::write(WriteStream & os) const +{ + if (os.latex()) + os << cell(0); + else + os << "\\lyxert{" << cell(0) << '}'; +} + + +void MathErtInset::infoize(std::ostream & os) const +{ + os << "Box: Ert"; +} + diff --git a/src/mathed/math_ertinset.h b/src/mathed/math_ertinset.h new file mode 100644 index 0000000000..1f50ce80d5 --- /dev/null +++ b/src/mathed/math_ertinset.h @@ -0,0 +1,26 @@ +#ifndef MATH_ERTINSET_H +#define MATH_ERTINSET_H + +#include "math_textinset.h" + +// implements support for \parbox + +class MathErtInset : public MathTextInset { +public: + /// + MathErtInset() {} + /// + MathInset * clone() const; + /// + mode_type currentMode() const { return TEXT_MODE; } + /// + void metrics(MathMetricsInfo & mi) const; + /// + void draw(MathPainterInfo & pi, int x, int y) const; + /// + void infoize(std::ostream & os) const; + /// + void write(WriteStream & os) const; +}; + +#endif diff --git a/src/mathed/math_factory.C b/src/mathed/math_factory.C index f07ebda69e..faa936b5a3 100644 --- a/src/mathed/math_factory.C +++ b/src/mathed/math_factory.C @@ -8,6 +8,7 @@ #include "math_casesinset.h" #include "math_decorationinset.h" #include "math_dotsinset.h" +#include "math_ertinset.h" #include "math_fboxinset.h" #include "math_fontinset.h" #include "math_fontoldinset.h" @@ -180,9 +181,39 @@ latexkeys const * in_word_set(string const & str) MathAtom createMathInset(string const & s) { lyxerr[Debug::MATHED] << "creating inset with name: '" << s << "'\n"; + latexkeys const * l = in_word_set(s); + if (l) { + string const & inset = l->inset; + lyxerr[Debug::MATHED] << " found inset: '" << inset << "'\n"; + if (inset == "ref") + return MathAtom(new RefInset(l->name)); + if (inset == "underset") + return MathAtom(new MathUndersetInset); + if (inset == "decoration") + return MathAtom(new MathDecorationInset(l)); + if (inset == "space") + return MathAtom(new MathSpaceInset(l->name)); + if (inset == "dots") + return MathAtom(new MathDotsInset(l)); + if (inset == "mbox") + return MathAtom(new MathBoxInset(l->name)); + if (inset == "parbox") + return MathAtom(new MathParboxInset); + if (inset == "fbox") + return MathAtom(new MathFboxInset(l)); + if (inset == "style") + return MathAtom(new MathSizeInset(l)); + if (inset == "font") + return MathAtom(new MathFontInset(l)); + if (inset == "oldfont") + return MathAtom(new MathFontOldInset(l)); + if (inset == "matrix") + return MathAtom(new MathAMSArrayInset(s)); + return MathAtom(new MathSymbolInset(l)); + } + if (s.size() == 2 && s[0] == '#' && s[1] >= '1' && s[1] <= '9') return MathAtom(new MathMacroArgument(s[1] - '0')); - if (s.size() == 3 && s[0] == '\\' && s[1] == '#' && s[2] >= '1' && s[2] <= '9') return MathAtom(new MathMacroArgument(s[2] - '0')); @@ -214,37 +245,8 @@ MathAtom createMathInset(string const & s) return MathAtom(new MathFracInset(true)); if (s == "lefteqn") return MathAtom(new MathLefteqnInset); - - latexkeys const * l = in_word_set(s); - if (l) { - string const & inset = l->inset; - lyxerr[Debug::MATHED] << " found inset: '" << inset << "'\n"; - if (inset == "ref") - return MathAtom(new RefInset(l->name)); - if (inset == "underset") - return MathAtom(new MathUndersetInset); - if (inset == "decoration") - return MathAtom(new MathDecorationInset(l)); - if (inset == "space") - return MathAtom(new MathSpaceInset(l->name)); - if (inset == "dots") - return MathAtom(new MathDotsInset(l)); - if (inset == "mbox") - return MathAtom(new MathBoxInset(l->name)); - if (inset == "parbox") - return MathAtom(new MathParboxInset); - if (inset == "fbox") - return MathAtom(new MathFboxInset(l)); - if (inset == "style") - return MathAtom(new MathSizeInset(l)); - if (inset == "font") - return MathAtom(new MathFontInset(l)); - if (inset == "oldfont") - return MathAtom(new MathFontOldInset(l)); - if (inset == "matrix") - return MathAtom(new MathAMSArrayInset(s)); - return MathAtom(new MathSymbolInset(l)); - } + if (s == "lyxert") + return MathAtom(new MathErtInset); if (MathMacroTable::has(s)) return MathAtom(new MathMacro(s)); diff --git a/src/mathed/math_gridinset.C b/src/mathed/math_gridinset.C index b8d484e862..afe1739645 100644 --- a/src/mathed/math_gridinset.C +++ b/src/mathed/math_gridinset.C @@ -128,8 +128,8 @@ void MathGridInset::setDefaults() { if (ncols() <= 0) lyxerr << "positive number of columns expected\n"; - if (nrows() <= 0) - lyxerr << "positive number of rows expected\n"; + //if (nrows() <= 0) + // lyxerr << "positive number of rows expected\n"; for (col_type col = 0; col < ncols(); ++col) { colinfo_[col].align_ = defaultColAlign(col); colinfo_[col].skip_ = defaultColSpace(col); diff --git a/src/mathed/math_gridinset.h b/src/mathed/math_gridinset.h index cecf1e8925..f25de29e6e 100644 --- a/src/mathed/math_gridinset.h +++ b/src/mathed/math_gridinset.h @@ -26,6 +26,13 @@ class MathGridInset : public MathNestInset { int dummy_; /// special multi colums alignment string align_; + /// these should be a per-cell property, but ok to have it here + /// for single-column grids like paragraphs + mutable int glue_; + /// + mutable pos_type begin_; + /// + mutable pos_type end_; }; /// additional per-row information @@ -198,9 +205,9 @@ public: //void octavize(OctaveStream &) const; protected: - /// returns x offset of cell comapared to inset + /// returns x offset of cell compared to inset int cellXOffset(idx_type idx) const; - /// returns y offset of cell comapared to inset + /// returns y offset of cell compared to inset int cellYOffset(idx_type idx) const; /// returns proper 'end of line' code for LaTeX string eolString(row_type row, bool fragile = false) const; @@ -209,6 +216,7 @@ protected: /// extract number of columns from alignment string col_type guessColumns(string const & halign) const; +public: /// row info std::vector rowinfo_; /// column info diff --git a/src/mathed/math_mathmlstream.C b/src/mathed/math_mathmlstream.C index 42ab2c1125..16f96e8625 100644 --- a/src/mathed/math_mathmlstream.C +++ b/src/mathed/math_mathmlstream.C @@ -280,7 +280,7 @@ WriteStream & operator<<(WriteStream & ws, MathArray const & ar) WriteStream & operator<<(WriteStream & ws, char const * s) { ws.os() << s; - ws.addlines(int(lyx::count(s, s+strlen(s), '\n'))); + ws.addlines(int(lyx::count(s, s + strlen(s), '\n'))); return ws; } @@ -288,8 +288,10 @@ WriteStream & operator<<(WriteStream & ws, char const * s) WriteStream & operator<<(WriteStream & ws, char c) { ws.os() << c; - if (c == '\n') + if (c == '\n') { + lyxerr << "writing a newline\n"; ws.addlines(1); + } return ws; } diff --git a/src/mathed/math_metricsinfo.C b/src/mathed/math_metricsinfo.C index 5bb81e2341..90d553c6f0 100644 --- a/src/mathed/math_metricsinfo.C +++ b/src/mathed/math_metricsinfo.C @@ -3,7 +3,6 @@ #include "math_metricsinfo.h" #include "math_support.h" -#include "debug.h" #include "frontends/Painter.h" diff --git a/src/mathed/math_parboxinset.C b/src/mathed/math_parboxinset.C index d96843ceb4..eac138f455 100644 --- a/src/mathed/math_parboxinset.C +++ b/src/mathed/math_parboxinset.C @@ -7,9 +7,9 @@ using std::vector; + MathParboxInset::MathParboxInset() - : MathNestInset(1), lyx_width_(0), tex_width_("0mm"), - position_('c') + : lyx_width_(0), tex_width_("0mm"), position_('c') { lyxerr << "constructing MathParboxInset\n"; } @@ -35,207 +35,23 @@ void MathParboxInset::setWidth(string const & w) } -int MathParboxInset::screenrows() const -{ - return rows_.size(); -} - - -int MathParboxInset::pos2row(pos_type pos) const -{ - for (int r = 0, n = rows_.size(); r < n; ++r) - if (pos >= rows_[r].begin && pos <= rows_[r].end) - return r; - lyxerr << "illegal row for pos " << pos << "\n"; - return 0; -} - - -void MathParboxInset::getPos(idx_type idx, pos_type pos, int & x, int & y) const -{ - int const r = pos2row(pos); - MathXArray const & ar = cells_[idx]; - x = ar.xo() + ar.pos2x(rows_[r].begin, pos, rows_[r].glue); - y = ar.yo() + rows_[r].yo; - // move cursor visually into empty cells ("blue rectangles"); - if (cell(0).empty()) - x += 2; - //lyxerr << "getPos cursor at pos " << pos << " in row " << r - // << " x: " << x << " y: " << y << "\n"; -} - - -bool MathParboxInset::idxUpDown(idx_type & idx, pos_type & pos, bool up, - int targetx) const -{ - // try to move only one screen row up or down if possible - int row = pos2row(pos); - int const x = cells_[idx].pos2x(rows_[row].begin, pos, rows_[row].glue); - if (up) { - if (row == 0) - return false; - --row; - } else { - ++row; - if (row == screenrows()) - return false; - } - pos = xcell(0).x2pos(rows_[row].begin, x, rows_[row].glue); - return true; -} - - void MathParboxInset::metrics(MathMetricsInfo & mi) const { - MathFontSetChanger dummy(mi.base, "textnormal"); - - // we do our own metrics fiddling - // delete old cache - rows_.clear(); - -#if 0 - - dim_ = xcell(0).metrics(mi); - -#else - - vector dims; - xcell(0).metricsExternal(mi, dims); - - int spaces = 0; - Dimension safe; - Dimension curr; - safe.clear(mi.base.font); - curr.clear(mi.base.font); - int begin = 0; - int safepos = 0; - int yo = 0; - for (size_type i = 0, n = cell(0).size(); i < n; ++i) { - //lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos - // << " curr: " << curr << " safe: " << safe - // << " spaces: " << spaces << endl; - - - // 0 1 2 3 4 5 6 - // - // ................... - // .......................... - // .................... - - // Special handling of spaces. We reached a safe position for breaking. - if (cell(0)[i]->getChar() == ' ') { - //lyxerr << "reached safe pos\n"; - // we don't count the space into the safe pos - safe += curr; - // we reset to this safepos if the next chunk does not fit - safepos = i; - ++spaces; - // restart chunk with size of the space - curr.clear(mi.base.font); - curr += dims[i]; - continue; - } - - // This is a regular char. Go on if we either don't care for - // the width limit or have not reached that limit. - curr += dims[i]; - if (curr.w + safe.w <= lyx_width_) - continue; - - // We passed the limit. Create a row entry. - //lyxerr << "passed limit\n"; - MathXArray::Row row; - if (spaces) { - // but we had a space break before this position. - // so retreat to this position - int glue = lyx_width_ - safe.w + dims[safepos].w; - row.dim = safe; - row.glue = glue / spaces; - row.begin = begin; - row.end = safepos; // this is position of the safe space - i = safepos; // i gets incremented at end of loop - begin = i + 1; // next chunk starts after the space - //lyxerr << "... but had safe pos. glue: " << row.glue << "\n"; - //lyxerr << " safe.w: " << safe.w - // << " dim.w: " << dims[safepos].w << " spaces: " << spaces << "\n"; - spaces = 0; - } else { - lyxerr << "... without safe pos\n"; - // This item is too large and it is the only one. - // We have no choice but to produce an overfull box. - row.dim = curr; // safe should be 0. - row.glue = 0; // does not matter - row.begin = begin; - row.end = i + 1; - begin = i + 1; - } - row.yo = yo; - yo += row.dim.height(); - rows_.push_back(row); - // in any case, start the new row with empty boxes - curr.clear(mi.base.font); - safe.clear(mi.base.font); - } - // last row: put in everything else - MathXArray::Row row; - row.dim = safe; - row.dim += curr; - row.begin = begin; - row.end = cell(0).size(); - row.glue = 0; // last line is left aligned - row.yo = yo; - rows_.push_back(row); - - // what to report? - dim_.w = lyx_width_; - dim_.a = rows_.front().dim.a; - dim_.d = rows_.back().dim.d + yo; + MathFontSetChanger dummy1(mi.base, "textnormal"); + MathWidthChanger dummy2(mi.base, lyx_width_); + MathTextInset::metrics(mi); metricsMarkers2(); - xcell(0).setDim(dim_); -#endif } void MathParboxInset::draw(MathPainterInfo & pi, int x, int y) const { MathFontSetChanger dummy(pi.base, "textnormal"); -#if 0 - xcell(0).draw(pi, x + 1, y); -#else - xcell(0).drawExternal(pi, x + 1, y, rows_); -#endif + MathTextInset::draw(pi, x + 1, y); drawMarkers2(pi, x, y); } -void MathParboxInset::drawSelection(MathPainterInfo & pi, - idx_type, pos_type pos1, idx_type, pos_type pos2) const -{ - int row1 = pos2row(pos1); - int row2 = pos2row(pos2); - if (row1 == row2) { -/* - MathXArray & c = xcell(0); - int x1 = c.xo() + c.pos2x(i1.pos_); - int y1 = c.yo() - c.ascent(); - int x2 = c.xo() + c.pos2x(i2.pos_); - int y2 = c.yo() + c.descent(); - pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection); - } else { - vector indices = idxBetween(idx1, idx2); - for (unsigned i = 0; i < indices.size(); ++i) { - MathXArray & c = i1.xcell(indices[i]); - int x1 = c.xo(); - int y1 = c.yo() - c.ascent(); - int x2 = c.xo() + c.width(); - int y2 = c.yo() + c.descent(); - pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection); - } -*/ - } -} - - void MathParboxInset::write(WriteStream & os) const { os << "\\parbox"; diff --git a/src/mathed/math_parboxinset.h b/src/mathed/math_parboxinset.h index bcf0dc606e..e03bf2de98 100644 --- a/src/mathed/math_parboxinset.h +++ b/src/mathed/math_parboxinset.h @@ -1,9 +1,11 @@ #ifndef MATH_PARBOXINSET_H #define MATH_PARBOXINSET_H -#include "math_nestinset.h" +#include "math_textinset.h" -class MathParboxInset : public MathNestInset { +// implements support for \parbox + +class MathParboxInset : public MathTextInset { public: /// MathParboxInset(); @@ -13,15 +15,10 @@ public: MathInset * clone() const; /// mode_type currentMode() const { return TEXT_MODE; } - /// get cursor position - void getPos(idx_type idx, pos_type pos, int & x, int & y) const; /// void metrics(MathMetricsInfo & mi) const; /// void draw(MathPainterInfo &, int x, int y) const; - /// draw selection background - void drawSelection(MathPainterInfo & pi, - idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const; /// void infoize(std::ostream & os) const; /// @@ -30,21 +27,13 @@ public: void setWidth(string const & width); /// void setPosition(string const & pos); - /// moves cursor up or down - bool idxUpDown(idx_type &, pos_type & pos, bool up, int targetx) const; private: - /// number of rows on screen - int screenrows() const; - /// row corresponding to given position - int pos2row(pos_type pos) const; /// width on screen int lyx_width_; /// width for TeX string tex_width_; - /// htb + /// one of htb char position_; - /// cached metrics - mutable std::vector rows_; }; #endif diff --git a/src/mathed/math_parinset.C b/src/mathed/math_parinset.C index 28af5f9ccb..96d4a6cb66 100644 --- a/src/mathed/math_parinset.C +++ b/src/mathed/math_parinset.C @@ -4,12 +4,6 @@ #include "debug.h" -MathParInset::MathParInset() -{ - lyxerr << "constructing MathParInset\n"; -} - - void MathParInset::metrics(MathMetricsInfo & mi) const { MathFontSetChanger dummy1(mi.base, "textnormal"); diff --git a/src/mathed/math_parinset.h b/src/mathed/math_parinset.h index 17811cb879..289f82aa13 100644 --- a/src/mathed/math_parinset.h +++ b/src/mathed/math_parinset.h @@ -6,7 +6,7 @@ class MathParInset : public MathHullInset { public: /// - MathParInset(); + MathParInset() {} /// mode_type currentMode() const { return TEXT_MODE; } /// diff --git a/src/mathed/math_parser.C b/src/mathed/math_parser.C index 32cd4c7f9f..56c8ca5332 100644 --- a/src/mathed/math_parser.C +++ b/src/mathed/math_parser.C @@ -69,14 +69,12 @@ following hack as starting point to write some macros: #include "support/lstrings.h" #include -#include #include using std::istream; using std::ostream; using std::ios; using std::endl; -using std::stack; using std::fill; using std::vector; using std::atoi; @@ -156,7 +154,7 @@ void catInit() theCatcode[''] = catIgnore; theCatcode[' '] = catSpace; theCatcode['\t'] = catSpace; - theCatcode['\r'] = catSpace; + theCatcode['\r'] = catNewline; theCatcode['~'] = catActive; theCatcode['%'] = catComment; } @@ -184,8 +182,6 @@ public: char character() const { return char_; } /// string asString() const; - /// - bool isCR() const; private: /// @@ -196,11 +192,6 @@ private: CatCode cat_; }; -bool Token::isCR() const -{ - return cs_ == "\\" || cs_ == "cr" || cs_ == "crcr"; -} - string Token::asString() const { return cs_.size() ? cs_ : string(1, char_); @@ -371,6 +362,17 @@ string Parser::getArg(char left, char right) } +void Parser::skipSpaceTokens(istream & is, char c) +{ + // skip trailing spaces + while (catcode(c) == catSpace || catcode(c) == catNewline) + if (!is.get(c)) + break; + //lyxerr << "putting back: " << c << "\n"; + is.putback(c); +} + + void Parser::tokenize(istream & is) { // eat everything up to the next \end_inset or end of stream @@ -390,17 +392,6 @@ void Parser::tokenize(istream & is) } -void Parser::skipSpaceTokens(istream & is, char c) -{ - // skip trailing spaces - while (catcode(c) == catSpace || catcode(c) == catNewline) - if (!is.get(c)) - break; - //lyxerr << "putting back: " << c << "\n"; - is.putback(c); -} - - void Parser::tokenize(string const & buffer) { static bool init_done = false; @@ -423,7 +414,7 @@ void Parser::tokenize(string const & buffer) if (catcode(c) == catNewline) ; //push_back(Token("par")); else { - push_back(Token(' ', catSpace)); + push_back(Token('\n', catNewline)); is.putback(c); } break; @@ -620,6 +611,9 @@ void Parser::parse1(MathGridInset & grid, unsigned flags, else if (t.cat() == catSpace && !mathmode) cell->push_back(MathAtom(new MathCharInset(t.character()))); + else if (t.cat() == catNewline && !mathmode) + cell->push_back(MathAtom(new MathCharInset(t.character()))); + else if (t.cat() == catParameter) { Token const & n = getToken(); cell->push_back(MathAtom(new MathMacroArgument(n.character()-'0'))); @@ -1065,8 +1059,13 @@ void Parser::parse1(MathGridInset & grid, unsigned flags, else { MathAtom p = createMathInset(t.cs()); + bool mode = mathmode; + if (mathmode && p->currentMode() == MathInset::TEXT_MODE) + mode = false; + if (!mathmode && p->currentMode() == MathInset::MATH_MODE) + mode = true; for (MathInset::idx_type i = 0; i < p->nargs(); ++i) - parse(p->cell(i), FLAG_ITEM, mathmode); + parse(p->cell(i), FLAG_ITEM, mode); cell->push_back(p); } } diff --git a/src/mathed/math_scriptinset.C b/src/mathed/math_scriptinset.C index ce1b4bef4b..eeccab358e 100644 --- a/src/mathed/math_scriptinset.C +++ b/src/mathed/math_scriptinset.C @@ -355,10 +355,10 @@ void MathScriptInset::write(WriteStream & os) const os << "{}"; } - if (hasDown() && down().data().size()) + if (hasDown() && down().size()) os << "_{" << down().data() << '}'; - if (hasUp() && up().data().size()) + if (hasUp() && up().size()) os << "^{" << up().data() << '}'; } @@ -423,8 +423,8 @@ void MathScriptInset::mathematicize(MathematicaStream & os) const void MathScriptInset::mathmlize( MathMLStream & os) const { - bool d = hasDown() && down().data().size(); - bool u = hasUp() && up().data().size(); + bool d = hasDown() && down().size(); + bool u = hasUp() && up().size(); if (u && d) os << MTag("msubsup"); diff --git a/src/mathed/math_support.C b/src/mathed/math_support.C index 23ffb03cb3..4dc8980364 100644 --- a/src/mathed/math_support.C +++ b/src/mathed/math_support.C @@ -557,6 +557,7 @@ fontinfo fontinfos[] = { {"textipa", inh_family, inh_series, inh_shape, LColor::black}, {"lyxtex", inh_family, inh_series, inh_shape, LColor::latex}, + {"lyxert", LyXFont::TYPEWRITER_FAMILY, inh_series, inh_shape, LColor::latex}, {"lyxsymbol", LyXFont::SYMBOL_FAMILY, inh_series, inh_shape, LColor::math}, {"lyxboldsymbol", LyXFont::SYMBOL_FAMILY, LyXFont::BOLD_SERIES, inh_shape, LColor::math}, diff --git a/src/mathed/math_textinset.C b/src/mathed/math_textinset.C new file mode 100644 index 0000000000..de7fd64e74 --- /dev/null +++ b/src/mathed/math_textinset.C @@ -0,0 +1,165 @@ + +#include "math_textinset.h" +#include "debug.h" + + +MathTextInset::MathTextInset() + : MathNestInset(1) +{} + + +MathInset * MathTextInset::clone() const +{ + return new MathTextInset(*this); +} + + +MathInset::idx_type MathTextInset::pos2row(pos_type pos) const +{ + for (pos_type r = 0, n = cache_.nargs(); r < n; ++r) + if (pos >= cache_.cellinfo_[r].begin_ && pos <= cache_.cellinfo_[r].end_) + return r; + lyxerr << "illegal row for pos " << pos << "\n"; + return 0; +} + + +void MathTextInset::getPos(idx_type, pos_type pos, int & x, int & y) const +{ + idx_type const i = pos2row(pos); + pos_type const p = pos - cache_.cellinfo_[i].begin_; + cache_.getPos(i, p, x, y); +} + + +bool MathTextInset::idxUpDown(idx_type &, pos_type & pos, bool up, + int targetx) const +{ + // try to move only one screen row up or down if possible + idx_type i = pos2row(pos); + MathGridInset::CellInfo const & cell1 = cache_.cellinfo_[i]; + int const x = cells_[0].pos2x(cell1.begin_, pos, cell1.glue_); + if (up) { + if (i == 0) + return false; + --i; + } else { + ++i; + if (i == cache_.nargs()) + return false; + } + MathGridInset::CellInfo const & cell2 = cache_.cellinfo_[i]; + pos = xcell(0).x2pos(cell2.begin_, x, cell2.glue_); + return true; +} + + +void MathTextInset::metrics(MathMetricsInfo & mi) const +{ + xcell(0).metrics(mi); + + // we do our own metrics fiddling + // delete old cache + cache_ = MathGridInset(1, 0); + + int spaces = 0; + int safe = 0; + int curr = 0; + int begin = 0; + int safepos = 0; + for (size_type i = 0, n = cell(0).size(); i < n; ++i) { + //lyxerr << "at pos: " << i << " of " << n << " safepos: " << safepos + // << " curr: " << curr << " safe: " << safe + // << " spaces: " << spaces << endl; + + // 0 1 2 3 4 5 6 + // + // ................... + // .......................... + // .................... + + // Special handling of spaces. We reached a safe position for breaking. + char const c = cell(0)[i]->getChar(); + if (c == ' ') { + //lyxerr << "reached safe pos\n"; + // we don't count the space into the safe pos + safe += curr; + // we reset to this safepos if the next chunk does not fit + safepos = i; + ++spaces; + // restart chunk with size of the space + curr = cell(0)[i]->width(); + continue; + } + + if (c != '\n') { + // This is a regular char. Go on if we either don't care for + // the width limit or have not reached that limit. + curr += cell(0)[i]->width(); + if (!mi.base.restrictwidth || curr + safe <= mi.base.textwidth) + continue; + } + + // We passed the limit. Create a row entry. + //lyxerr << "passed limit\n"; + cache_.appendRow(); + MathXArray & ar = cache_.xcell(cache_.nargs() - 1); + MathGridInset::CellInfo & row = cache_.cellinfo_.back(); + if (c == '\n') { + // we are here because we hit a hard newline + row.begin_ = begin; + row.end_ = i + 1; + begin = i + 1; // next chunk starts after the newline + spaces = 0; + } else if (spaces) { + // but we had a space break before this position. + // so retreat to this position + //lyxerr << "... but had safe pos.\n"; + row.begin_ = begin; + row.end_ = safepos; // this is position of the safe space + i = safepos; // i gets incremented at end of loop + begin = i + 1; // next chunk starts after the space + spaces = 0; + } else { + // This item is too large and it is the only one. + // We have no choice but to produce an overfull box. + lyxerr << "... without safe pos\n"; + row.begin_ = begin; + row.end_ = i + 1; + begin = i + 1; + } + ar.data() = + MathArray(cell(0).begin() + row.begin_, cell(0).begin() + row.end_); + //lyxerr << "line: " << ar << "\n"; + // in any case, start the new row with empty boxes + curr = 0; + safe = 0; + } + // last row: put in everything else + cache_.appendRow(); + MathXArray & ar = cache_.xcell(cache_.nargs() - 1); + MathGridInset::CellInfo & row = cache_.cellinfo_.back(); + row.begin_ = begin; + row.end_ = cell(0).size(); + ar.data() = + MathArray(cell(0).begin() + row.begin_, cell(0).begin() + row.end_); + //lyxerr << "last line: " << ar.data() << "\n"; + + // what to report? + cache_.metrics(mi); + dim_ = cache_.dimensions(); + //lyxerr << "outer dim: " << dim_ << endl; +} + + +void MathTextInset::draw(MathPainterInfo & pi, int x, int y) const +{ + cache_.draw(pi, x + 1, y); +} + + +void MathTextInset::drawSelection(MathPainterInfo & pi, + idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const +{ + cache_.drawSelection(pi, idx1, pos1, idx2, pos2); +} diff --git a/src/mathed/math_textinset.h b/src/mathed/math_textinset.h new file mode 100644 index 0000000000..309d319ce1 --- /dev/null +++ b/src/mathed/math_textinset.h @@ -0,0 +1,32 @@ +#ifndef MATH_TEXTINSET_H +#define MATH_TEXTINSET_H + +#include "math_gridinset.h" + +// not yet a substitute for the real text inset... + +class MathTextInset : public MathNestInset { +public: + /// + MathTextInset(); + /// + MathInset * clone() const; + /// get cursor position + void getPos(idx_type idx, pos_type pos, int & x, int & y) const; + /// this stores metrics information in cache_ + void metrics(MathMetricsInfo & mi) const; + /// draw according to cached metrics + void draw(MathPainterInfo &, int x, int y) const; + /// draw selection background + void drawSelection(MathPainterInfo & pi, + idx_type idx1, pos_type pos1, idx_type idx2, pos_type pos2) const; + /// moves cursor up or down + bool idxUpDown(idx_type &, pos_type & pos, bool up, int targetx) const; +protected: + /// row corresponding to given position + idx_type pos2row(pos_type pos) const; + /// cached metrics + mutable MathGridInset cache_; +}; + +#endif diff --git a/src/mathed/math_xdata.C b/src/mathed/math_xdata.C index 4137afd8e1..3e6d47f6d8 100644 --- a/src/mathed/math_xdata.C +++ b/src/mathed/math_xdata.C @@ -50,38 +50,11 @@ Dimension const & MathXArray::metrics(MathMetricsInfo & mi) const } -void MathXArray::metricsExternal(MathMetricsInfo & mi, - std::vector & v) const -{ - //if (clean_) - // return; - - clean_ = true; - drawn_ = false; - - if (empty()) { - mathed_char_dim(mi.base.font, 'I', dim_); - return; - } - - dim_.clear(); - for (const_iterator it = begin(), et = end(); it != et; ++it) { - MathInset const * p = it->nucleus(); - p->metrics(mi); - v.push_back(p->dimensions()); - } - //for (int i = 0; i < size(); ++i) - // lyxerr << "i: " << i << " dim: " << v[i] << endl; - //lyxerr << "MathXArray::metrics(): '" << dim_ << "\n"; -} - - void MathXArray::draw(MathPainterInfo & pi, int x, int y) const { //if (drawn_ && x == xo_ && y == yo_) // return; - - //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl; + //lyxerr << "MathXArray::draw: x: " << x << " y: " << y << endl; xo_ = x; yo_ = y; @@ -96,48 +69,18 @@ void MathXArray::draw(MathPainterInfo & pi, int x, int y) const if (x >= pi.pain.paperWidth()) // don't draw right of workarea return; - const_iterator it = begin(), et = end(); - - if (it == et) { + if (empty()) { pi.pain.rectangle(x, y - ascent(), width(), height(), LColor::mathline); return; } - for (; it != et; ++it) { + for (const_iterator it = begin(), et = end(); it != et; ++it) { (*it)->draw(pi, x, y); x += (*it)->width(); } } -void MathXArray::drawExternal(MathPainterInfo & pi, int x, int y, - std::vector const & v) const -{ - //for (size_type r = 0; r < v.size(); ++r) - // lyxerr << "row " << r << " to: " << v[r].end << endl; - //lyxerr << " data: " << *this << endl; - - xo_ = x; - yo_ = y; - - for (size_type r = 0; r < v.size(); ++r) { - int xx = x; - int yy = y + v[r].yo; - for (size_type pos = v[r].begin; pos < v[r].end && pos < size(); ++pos) { - //lyxerr << "drawing pos " << pos << " of " << size() - // << " " << int(operator[](pos)->getChar()) << endl; - MathInset const * p = operator[](pos).nucleus(); - // insert extra glue if necessary - if (p->getChar() == ' ') - xx += v[r].glue; - // ordinary case - p->draw(pi, xx, yy); - xx += p->width(); - } - } -} - - Dimension const & MathXArray::metricsT(TextMetricsInfo const & mi) const { //if (clean_) @@ -155,19 +98,14 @@ void MathXArray::drawT(TextPainter & pain, int x, int y) const { //if (drawn_ && x == xo_ && y == yo_) // return; - //lyxerr << "x: " << x << " y: " << y << " " << pain.workAreaHeight() << endl; - xo_ = x; yo_ = y; drawn_ = true; - const_iterator it = begin(), et = end(); - - for (; it != et; ++it) { - MathInset const * p = it->nucleus(); - p->drawT(pain, x, y); - x += p->width(); + for (const_iterator it = begin(), et = end(); it != et; ++it) { + (*it)->drawT(pain, x, y); + x += (*it)->width(); } } @@ -282,3 +220,10 @@ void MathXArray::towards(int & x, int & y) const x = cx + int(r * (x - cx)); y = cy + int(r * (y - cy)); } + + +std::ostream & operator<<(std::ostream & os, MathXArray const & ar) +{ + os << ar.data(); +} + diff --git a/src/mathed/math_xdata.h b/src/mathed/math_xdata.h index 90b1bd9864..7045208394 100644 --- a/src/mathed/math_xdata.h +++ b/src/mathed/math_xdata.h @@ -36,34 +36,12 @@ public: MathArray & data() { return *this; } MathArray const & data() const { return *this; } - // helper structure for external metrics computations as done - // in parboxes - struct Row { - /// constructor - Row() {} - /// first position of this row - size_type begin; - /// last position of this row plus one - size_type end; - /// y offset relative to yo - int yo; - /// dimensions of this row - Dimension dim; - /// glue between words - int glue; - }; - /// constructor MathXArray(); /// rebuild cached metrics information Dimension const & metrics(MathMetricsInfo & mi) const; - /// rebuild cached metrics information - void metricsExternal(MathMetricsInfo & mi, std::vector &) const; /// redraw cell using cache metrics information void draw(MathPainterInfo & pi, int x, int y) const; - /// redraw cell using external metrics information - void drawExternal(MathPainterInfo & pi, int x, int y, - std::vector const &) const; /// rebuild cached metrics information Dimension const & metricsT(TextMetricsInfo const & mi) const; /// redraw cell using cache metrics information -- 2.39.2