]> git.lyx.org Git - lyx.git/blobdiff - src/mathed/InsetMathHull.cpp
Change the interface to a paragraph's layout. We still store a LayoutPtr, but now...
[lyx.git] / src / mathed / InsetMathHull.cpp
index 9a1afc01052019f35909f48969ec063f1d6fc189..b7de48c89f537078e2de2d797c9c5b347a800c94 100644 (file)
 #include "FuncStatus.h"
 #include "LaTeXFeatures.h"
 #include "Cursor.h"
-#include "support/debug.h"
 #include "DispatchResult.h"
 #include "FuncRequest.h"
-#include "support/gettext.h"
 #include "LyXRC.h"
 #include "OutputParams.h"
+#include "ParIterator.h"
 #include "sgml.h"
 #include "Text.h"
 #include "TextPainter.h"
+#include "TocBackend.h"
 
 #include "insets/RenderPreview.h"
 #include "insets/InsetLabel.h"
@@ -50,6 +50,8 @@
 
 #include "frontends/Painter.h"
 
+#include "support/debug.h"
+#include "support/gettext.h"
 #include "support/lstrings.h"
 
 #include <sstream>
@@ -138,9 +140,10 @@ docstring hullName(HullType type)
        }
 }
 
+static InsetLabel * dummy_pointer = 0;
 
 InsetMathHull::InsetMathHull()
-       : InsetMathGrid(1, 1), type_(hullNone), nonum_(1), label_(1),
+       : InsetMathGrid(1, 1), type_(hullNone), nonum_(1, false), label_(1, dummy_pointer),
          preview_(new RenderPreview(this))
 {
        //lyxerr << "sizeof InsetMath: " << sizeof(InsetMath) << endl;
@@ -153,7 +156,7 @@ InsetMathHull::InsetMathHull()
 
 
 InsetMathHull::InsetMathHull(HullType type)
-       : InsetMathGrid(getCols(type), 1), type_(type), nonum_(1), label_(1),
+       : InsetMathGrid(getCols(type), 1), type_(type), nonum_(1, false), label_(1, dummy_pointer),
          preview_(new RenderPreview(this))
 {
        initMath();
@@ -162,14 +165,16 @@ InsetMathHull::InsetMathHull(HullType type)
 
 
 InsetMathHull::InsetMathHull(InsetMathHull const & other)
-       : InsetMathGrid(other),
-         type_(other.type_), nonum_(other.nonum_), label_(other.label_),
-         preview_(new RenderPreview(*other.preview_, this))
-{}
+{
+       operator=(other);
+}
 
 
 InsetMathHull::~InsetMathHull()
-{}
+{
+       for (size_t i = 0; i < label_.size(); ++i)
+               delete label_[i];
+}
 
 
 Inset * InsetMathHull::clone() const
@@ -182,16 +187,78 @@ InsetMathHull & InsetMathHull::operator=(InsetMathHull const & other)
 {
        if (this == &other)
                return *this;
-       *static_cast<InsetMathGrid*>(this) = InsetMathGrid(other);
+       InsetMathGrid::operator=(other);
        type_  = other.type_;
        nonum_ = other.nonum_;
+       for (size_t i = 0; i < label_.size(); ++i)
+               delete label_[i];
        label_ = other.label_;
+       for (size_t i = 0; i != label_.size(); ++i) {
+               if (label_[i])
+                       label_[i] = new InsetLabel(*label_[i]);
+       }
        preview_.reset(new RenderPreview(*other.preview_, this));
 
        return *this;
 }
 
 
+void InsetMathHull::setBuffer(Buffer & buffer)
+{
+       buffer_ = &buffer;
+       for (idx_type i = 0, n = nargs(); i != n; ++i) {
+               MathData & data = cell(i);
+               for (size_t j = 0; j != data.size(); ++j)
+                       data[j].nucleus()->setBuffer(buffer);
+       }
+
+       for (size_t i = 0; i != label_.size(); ++i) {
+               if (label_[i])
+                       label_[i]->setBuffer(buffer);
+       }
+}
+
+
+void InsetMathHull::updateLabels(ParIterator const & it)
+{
+       if (!buffer_) {
+               //FIXME: buffer_ should be set at creation for this inset! Problem is
+               // This inset is created at too many places (see Parser::parse1() in
+               // MathParser.cpp).
+               return;
+       }
+       for (size_t i = 0; i != label_.size(); ++i) {
+               if (label_[i])
+                       label_[i]->updateLabels(it);
+       }
+}
+
+
+void InsetMathHull::addToToc(ParConstIterator const & pit) const
+{
+       if (!buffer_) {
+               //FIXME: buffer_ should be set at creation for this inset! Problem is
+               // This inset is created at too many places (see Parser::parse1() in
+               // MathParser.cpp).
+               return;
+       }
+
+       // FIXME: it would be way better to directly use InsetLabel instead of this
+       // label list. But it should be possible to copy&paste the code in
+       // InsetLabel::addToToc() anyway.
+
+       Toc & toc = buffer().tocBackend().toc("equation");
+
+       for (row_type row = 0; row != nrows(); ++row) {
+               if (nonum_[row])
+                       continue;
+               if (label_[row])
+                       label_[row]->addToToc(pit);
+               toc.push_back(TocItem(pit, 0, nicelabel(row)));
+       }
+}
+
+
 Inset * InsetMathHull::editXY(Cursor & cur, int x, int y)
 {
        if (use_preview_) {
@@ -231,6 +298,8 @@ char InsetMathHull::defaultColAlign(col_type col)
 {
        if (type_ == hullEqnArray)
                return "rcl"[col];
+       if (type_ == hullGather)
+               return 'c';
        if (type_ >= hullAlign)
                return "rl"[col & 1];
        return 'c';
@@ -397,7 +466,7 @@ void InsetMathHull::addPreview(graphics::PreviewLoader & ploader) const
 }
 
 
-bool InsetMathHull::notifyCursorLeaves(Cursor & cur)
+bool InsetMathHull::notifyCursorLeaves(Cursor const & /*old*/, Cursor & cur)
 {
        if (RenderPreview::status() == LyXRC::PREVIEW_ON) {
                Buffer const & buffer = cur.buffer();
@@ -413,22 +482,34 @@ bool InsetMathHull::notifyCursorLeaves(Cursor & cur)
 docstring InsetMathHull::label(row_type row) const
 {
        BOOST_ASSERT(row < nrows());
-       return label_[row];
+       if (InsetLabel * il = label_[row])
+               return il->screenLabel();
+       return docstring();
 }
 
 
 void InsetMathHull::label(row_type row, docstring const & label)
 {
        //lyxerr << "setting label '" << label << "' for row " << row << endl;
-       label_[row] = label;
+       if (label_[row]) {
+               label_[row]->updateCommand(label);
+               return;
+       }
+       InsetCommandParams p(LABEL_CODE);
+       p["name"] = label;
+       label_[row] = new InsetLabel(p);
+       if (buffer_)
+               label_[row]->setBuffer(buffer());
 }
 
 
 void InsetMathHull::numbered(row_type row, bool num)
 {
        nonum_[row] = !num;
-       if (nonum_[row])
-               label_[row].clear();
+       if (nonum_[row] && label_[row]) {
+               delete label_[row];
+               label_[row] = 0;
+       }
 }
 
 
@@ -457,11 +538,11 @@ Inset::DisplayType InsetMathHull::display() const
 }
 
 
-void InsetMathHull::getLabelList(Buffer const &, vector<docstring> & labels) const
+void InsetMathHull::getLabelList(vector<docstring> & labels) const
 {
        for (row_type row = 0; row < nrows(); ++row)
-               if (!label_[row].empty() && nonum_[row] != 1)
-                       labels.push_back(label_[row]);
+               if (label_[row] && !nonum_[row])
+                       labels.push_back(label_[row]->screenLabel());
 }
 
 
@@ -609,7 +690,7 @@ void InsetMathHull::addRow(row_type row)
        if (!rowChangeOK())
                return;
        nonum_.insert(nonum_.begin() + row + 1, !numberedType());
-       label_.insert(label_.begin() + row + 1, docstring());
+       label_.insert(label_.begin() + row + 1, dummy_pointer);
        InsetMathGrid::addRow(row);
 }
 
@@ -620,7 +701,12 @@ void InsetMathHull::swapRow(row_type row)
                return;
        if (row + 1 == nrows())
                --row;
-       swap(nonum_[row], nonum_[row + 1]);
+       // gcc doesn't like this:
+       //      swap(nonum_[row], nonum_[row + 1]);
+       // so we do it manually:
+       bool const b = nonum_[row];
+       nonum_[row] = nonum_[row + 1];
+       nonum_[row + 1] = b;
        swap(label_[row], label_[row + 1]);
        InsetMathGrid::swapRow(row);
 }
@@ -636,6 +722,7 @@ void InsetMathHull::delRow(row_type row)
        if (row == nrows() + 1)
                row--;
        nonum_.erase(nonum_.begin() + row);
+       delete label_[row];
        label_.erase(label_.begin() + row);
 }
 
@@ -660,9 +747,9 @@ docstring InsetMathHull::nicelabel(row_type row) const
 {
        if (nonum_[row])
                return docstring();
-       if (label_[row].empty())
+       if (!label_[row])
                return from_ascii("(#)");
-       return '(' + label_[row] + ')';
+       return '(' + label_[row]->screenLabel() + ')';
 }
 
 
@@ -809,23 +896,23 @@ void InsetMathHull::mutate(HullType newtype)
        else if (type_ == hullEqnArray) {
                if (newtype < type_) {
                        // set correct (no)numbering
-                       bool allnonum = true;
-                       for (row_type row = 0; row < nrows(); ++row)
-                               if (!nonum_[row])
-                                       allnonum = false;
+                       nonum_[0] = true;
+                       for (row_type row = 0; row < nrows(); ++row) {
+                               if (!nonum_[row]) {
+                                       nonum_[0] = false;
+                                       break;
+                               }
+                       }
 
                        // set first non-empty label
-                       docstring label;
                        for (row_type row = 0; row < nrows(); ++row) {
-                               if (!label_[row].empty()) {
-                                       label = label_[row];
+                               if (label_[row]) {
+                                       label_[0] = label_[row];
                                        break;
                                }
                        }
 
                        glueall();
-                       nonum_[0] = allnonum;
-                       label_[0] = label;
                        mutate(newtype);
                } else { // align & Co.
                        changeCols(2);
@@ -898,8 +985,8 @@ docstring InsetMathHull::eolString(row_type row, bool emptyline, bool fragile) c
 {
        docstring res;
        if (numberedType()) {
-               if (!label_[row].empty() && !nonum_[row])
-                       res += "\\label{" + label_[row] + '}';
+               if (label_[row] && !nonum_[row])
+                       res += "\\label{" + label_[row]->getParam("name") + '}';
                if (nonum_[row] && (type_ != hullMultline))
                        res += "\\nonumber ";
        }
@@ -1025,9 +1112,10 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_FINISHED_BACKWARD:
        case LFUN_FINISHED_FORWARD:
+       case LFUN_FINISHED_RIGHT:
+       case LFUN_FINISHED_LEFT:
                //lyxerr << "action: " << cmd.action << endl;
                InsetMathGrid::doDispatch(cur, cmd);
-               notifyCursorLeaves(cur);
                cur.undispatched();
                break;
 
@@ -1048,30 +1136,28 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd)
                InsetMathGrid::doDispatch(cur, cmd);
                break;
 
-       case LFUN_MATH_NUMBER:
+       case LFUN_MATH_NUMBER_TOGGLE: {
                //lyxerr << "toggling all numbers" << endl;
-               if (display()) {
-                       cur.recordUndoInset();
-                       bool old = numberedType();
-                       if (type_ == hullMultline)
-                               numbered(nrows() - 1, !old);
-                       else
-                               for (row_type row = 0; row < nrows(); ++row)
-                                       numbered(row, !old);
-
-                       cur.message(old ? _("No number") : _("Number"));
-               }
+               cur.recordUndoInset();
+               bool old = numberedType();
+               if (type_ == hullMultline)
+                       numbered(nrows() - 1, !old);
+               else
+                       for (row_type row = 0; row < nrows(); ++row)
+                               numbered(row, !old);
+               
+               cur.message(old ? _("No number") : _("Number"));
                break;
+       }
 
-       case LFUN_MATH_NONUMBER:
-               if (display()) {
-                       cur.recordUndoInset();
-                       row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
-                       bool old = numbered(r);
-                       cur.message(old ? _("No number") : _("Number"));
-                       numbered(r, !old);
-               }
+       case LFUN_MATH_NUMBER_LINE_TOGGLE: {
+               cur.recordUndoInset();
+               row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
+               bool old = numbered(r);
+               cur.message(old ? _("No number") : _("Number"));
+               numbered(r, !old);
                break;
+       }
 
        case LFUN_LABEL_INSERT: {
                cur.recordUndoInset();
@@ -1097,6 +1183,7 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd)
 
        case LFUN_INSET_INSERT: {
                //lyxerr << "arg: " << to_utf8(cmd.argument()) << endl;
+               // FIXME: this should be cleaned up to use InsetLabel methods directly.
                string const name = cmd.getArg(0);
                if (name == "label") {
                        InsetCommandParams p(LABEL_CODE);
@@ -1109,9 +1196,14 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd)
                                numbered(r, true);
                        docstring old = label(r);
                        if (str != old) {
-                               cur.bv().buffer().changeRefsIfUnique(old, str,
-                                                       REF_CODE);
-                               label(r, str);
+                               if (label_[r])
+                                       // The label will take care of the reference update.
+                                       label(r, str);
+                               else {
+                                       label(r, str);
+                                       // Newly created inset so initialize it.
+                                       label_[r]->initView();
+                               }
                        }
                        break;
                }
@@ -1136,6 +1228,10 @@ void InsetMathHull::doDispatch(Cursor & cur, FuncRequest & cmd)
                }
                if (cur.pos() > cur.lastpos())
                        cur.pos() = cur.lastpos();
+               
+               // FIXME: find some more clever handling of the selection,
+               // i.e. preserve it.
+               cur.clearSelection();
                //cur.dispatched(FINISHED);
                break;
        }
@@ -1162,19 +1258,31 @@ bool InsetMathHull::getStatus(Cursor & cur, FuncRequest const & cmd,
        switch (cmd.action) {
        case LFUN_FINISHED_BACKWARD:
        case LFUN_FINISHED_FORWARD:
+       case LFUN_FINISHED_RIGHT:
+       case LFUN_FINISHED_LEFT:
        case LFUN_UP:
        case LFUN_DOWN:
-               status.enabled(true);
-               return true;
        case LFUN_NEW_LINE:
-       case LFUN_MATH_NUMBER:
-       case LFUN_MATH_NONUMBER:
        case LFUN_MATH_EXTERN:
        case LFUN_MATH_MUTATE:
        case LFUN_MATH_DISPLAY:
                // we handle these
                status.enabled(true);
                return true;
+       case LFUN_MATH_NUMBER_TOGGLE:
+               // FIXME: what is the right test, this or the one of
+               // LABEL_INSERT?
+               status.enabled(display());
+               status.setOnOff(numberedType());
+               return true;
+       case LFUN_MATH_NUMBER_LINE_TOGGLE: {
+               // FIXME: what is the right test, this or the one of
+               // LABEL_INSERT?
+               status.enabled(display());
+               row_type const r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
+               status.setOnOff(numbered(r));
+               return true;
+       }
        case LFUN_LABEL_INSERT:
                status.enabled(type_ != hullSimple);
                return true;
@@ -1296,10 +1404,12 @@ void InsetMathHull::handleFont2(Cursor & cur, docstring const & arg)
 }
 
 
-void InsetMathHull::edit(Cursor & cur, bool front)
+void InsetMathHull::edit(Cursor & cur, bool front, EntryDirection entry_from)
 {
        cur.push(*this);
-       front ? idxFirst(cur) : idxLast(cur);
+       bool enter_front = (entry_from == Inset::ENTRY_DIRECTION_LEFT || 
+               (entry_from == Inset::ENTRY_DIRECTION_IGNORE && front));
+       enter_front ? idxFirst(cur) : idxLast(cur);
        // The inset formula dimension is not necessarily the same as the
        // one of the instant preview image, so we have to indicate to the
        // BufferView that a metrics update is needed.
@@ -1307,7 +1417,7 @@ void InsetMathHull::edit(Cursor & cur, bool front)
 }
 
 
-docstring const InsetMathHull::editMessage() const
+docstring InsetMathHull::editMessage() const
 {
        return _("Math editor mode");
 }
@@ -1399,7 +1509,7 @@ bool InsetMathHull::searchForward(BufferView * bv, string const & str,
 #endif
 
 
-void InsetMathHull::write(Buffer const &, ostream & os) const
+void InsetMathHull::write(ostream & os) const
 {
        odocstringstream oss;
        WriteStream wi(oss, false, false);
@@ -1409,7 +1519,7 @@ void InsetMathHull::write(Buffer const &, ostream & os) const
 }
 
 
-void InsetMathHull::read(Buffer const &, Lexer & lex)
+void InsetMathHull::read(Lexer & lex)
 {
        MathAtom at;
        mathed_parse_normal(at, lex);
@@ -1417,8 +1527,7 @@ void InsetMathHull::read(Buffer const &, Lexer & lex)
 }
 
 
-int InsetMathHull::plaintext(Buffer const &, odocstream & os,
-                            OutputParams const &) const
+int InsetMathHull::plaintext(odocstream & os, OutputParams const &) const
 {
        if (0 && display()) {
                Dimension dim;
@@ -1442,8 +1551,7 @@ int InsetMathHull::plaintext(Buffer const &, odocstream & os,
 }
 
 
-int InsetMathHull::docbook(Buffer const & buf, odocstream & os,
-                          OutputParams const & runparams) const
+int InsetMathHull::docbook(odocstream & os, OutputParams const & runparams) const
 {
        MathStream ms(os);
        int res = 0;
@@ -1455,7 +1563,7 @@ int InsetMathHull::docbook(Buffer const & buf, odocstream & os,
 
        docstring bname = name;
        if (!label(0).empty())
-               bname += " id='" + sgml::cleanID(buf, runparams, label(0)) + "'";
+               bname += " id='" + sgml::cleanID(buffer(), runparams, label(0)) + "'";
 
        ++ms.tab(); ms.cr(); ms.os() << '<' << bname << '>';
 
@@ -1476,14 +1584,14 @@ int InsetMathHull::docbook(Buffer const & buf, odocstream & os,
                ms << ETag("math");
        } else {
                ms << MTag("alt role='tex'");
-               res = latex(buf, ls, runparams);
+               res = latex(ls, runparams);
                ms << from_utf8(subst(subst(to_utf8(ls.str()), "&", "&amp;"), "<", "&lt;"));
                ms << ETag("alt");
        }
 
        ms << from_ascii("<graphic fileref=\"eqn/");
        if (!label(0).empty())
-               ms << sgml::cleanID(buf, runparams, label(0));
+               ms << sgml::cleanID(buffer(), runparams, label(0));
        else
                ms << sgml::uniqueID(from_ascii("anon"));
 
@@ -1498,9 +1606,9 @@ int InsetMathHull::docbook(Buffer const & buf, odocstream & os,
 }
 
 
-void InsetMathHull::textString(Buffer const & buf, odocstream & os) const
+void InsetMathHull::textString(odocstream & os) const
 {
-       plaintext(buf, os, OutputParams(0));
+       plaintext(os, OutputParams(0));
 }