* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
- * \author André Pönitz
+ * \author André Pönitz
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
+#include "BufferView.h"
+#include "Cursor.h"
+#include "DispatchResult.h"
+#include "FuncRequest.h"
+#include "InsetMathFont.h"
#include "InsetMathScript.h"
+#include "InsetMathSymbol.h"
+#include "LaTeXFeatures.h"
#include "MathData.h"
#include "MathStream.h"
#include "MathSupport.h"
-#include "InsetMathSymbol.h"
-#include "InsetMathFont.h"
-#include "DispatchResult.h"
-#include "Cursor.h"
+
#include "support/debug.h"
-#include "FuncRequest.h"
-#include <boost/assert.hpp>
+#include "support/lassert.h"
#include <ostream>
+using namespace std;
namespace lyx {
-using std::string;
-using std::max;
-InsetMathScript::InsetMathScript()
- : InsetMathNest(1), cell_1_is_up_(false), limits_(0)
+InsetMathScript::InsetMathScript(Buffer * buf)
+ : InsetMathNest(buf, 1), cell_1_is_up_(false), limits_(0)
{}
-InsetMathScript::InsetMathScript(bool up)
- : InsetMathNest(2), cell_1_is_up_(up), limits_(0)
+InsetMathScript::InsetMathScript(Buffer * buf, bool up)
+ : InsetMathNest(buf, 2), cell_1_is_up_(up), limits_(0)
{}
-InsetMathScript::InsetMathScript(MathAtom const & at, bool up)
- : InsetMathNest(2), cell_1_is_up_(up), limits_(0)
+InsetMathScript::InsetMathScript(Buffer * buf, MathAtom const & at, bool up)
+ : InsetMathNest(buf, 2), cell_1_is_up_(up), limits_(0)
{
- BOOST_ASSERT(nargs() >= 1);
+ LASSERT(nargs() >= 1, /**/);
cell(0).push_back(at);
}
{
if (nargs() == 3)
return cell(2);
- BOOST_ASSERT(nargs() > 1);
+ LASSERT(nargs() > 1, /**/);
return cell(1);
}
{
if (nargs() == 3)
return cell(2);
- BOOST_ASSERT(nargs() > 1);
+ LASSERT(nargs() > 1, /**/);
return cell(1);
}
MathData const & InsetMathScript::up() const
{
- BOOST_ASSERT(nargs() > 1);
+ LASSERT(nargs() > 1, /**/);
return cell(1);
}
MathData & InsetMathScript::up()
{
- BOOST_ASSERT(nargs() > 1);
+ LASSERT(nargs() > 1, /**/);
return cell(1);
}
int InsetMathScript::dx0(BufferView const & bv) const
{
- BOOST_ASSERT(hasDown());
+ LASSERT(hasDown(), /**/);
Dimension const dim = dimension(bv);
return hasLimits() ? (dim.wid - down().dimension(bv).width()) / 2 : nwid(bv);
}
int InsetMathScript::dx1(BufferView const & bv) const
{
- BOOST_ASSERT(hasUp());
+ LASSERT(hasUp(), /**/);
Dimension const dim = dimension(bv);
- return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2 : nwid(bv) + nker();
+ return hasLimits() ? (dim.wid - up().dimension(bv).width()) / 2 : nwid(bv) + nker(&bv);
}
}
-int InsetMathScript::nker() const
+int InsetMathScript::nker(BufferView const * bv) const
{
if (nuc().size()) {
- int kerning = nuc().kerning();
+ int kerning = nuc().kerning(bv);
return kerning > 0 ? kerning : 0;
}
return 0;
dim.wid = max(dim.wid, dimdown.width());
} else {
if (hasUp())
- dim.wid = max(dim.wid, nker() + dimup.width());
+ dim.wid = max(dim.wid, nker(mi.base.bv) + dimup.width());
if (hasDown())
dim.wid = max(dim.wid, dimdown.width());
dim.wid += nwid(bv);
} else
dim.des = nd;
metricsMarkers(dim);
- // Cache the inset dimension.
- setDimCache(mi, dim);
}
return (cell_1_is_up_ == up) ? 1 : 0;
if (nargs() == 3)
return up ? 1 : 2;
- BOOST_ASSERT(false);
+ LASSERT(false, /**/);
// Silence compiler
return 0;
}
void InsetMathScript::write(WriteStream & os) const
{
+ MathEnsurer ensurer(os);
+
if (nuc().size()) {
os << nuc();
//if (nuc().back()->takesLimits()) {
}
+// FIXME XHTML
+// It may be worth trying to output munder, mover, and munderover
+// in certain cases, e.g., for display formulas. But then we would
+// need to know if we're in a display formula.
void InsetMathScript::mathmlize(MathStream & os) const
{
bool d = hasDown() && down().size();
os << MTag("msub");
if (nuc().size())
- os << nuc();
+ os << MTag("mrow") << nuc() << ETag("mrow");
else
- os << "<mrow/>";
+ os << "<mrow />";
if (u && d)
- os << down() << up() << ETag("msubsup");
+ os << MTag("mrow") << down() << ETag("mrow")
+ << MTag("mrow") << up() << ETag("mrow")
+ << ETag("msubsup");
else if (u)
- os << up() << ETag("msup");
+ os << MTag("mrow") << up() << ETag("mrow") << ETag("msup");
else if (d)
- os << down() << ETag("msub");
+ os << MTag("mrow") << down() << ETag("mrow") << ETag("msub");
+}
+
+
+void InsetMathScript::htmlize(HtmlStream & os) const
+{
+ bool d = hasDown() && down().size();
+ bool u = hasUp() && up().size();
+
+ if (nuc().size())
+ os << nuc();
+
+ if (u && d)
+ os << MTag("span", "class='scripts'")
+ << MTag("span") << up() << ETag("span")
+ << MTag("span") << down() << ETag("span")
+ << ETag("span");
+ else if (u)
+ os << MTag("sup", "class='math'") << up() << ETag("sup");
+ else if (d)
+ os << MTag("sub", "class='math'") << down() << ETag("sub");
}
}
-bool InsetMathScript::notifyCursorLeaves(Cursor & cur)
+bool InsetMathScript::notifyCursorLeaves(Cursor const & old, Cursor & cur)
{
- InsetMathNest::notifyCursorLeaves(cur);
+ InsetMathNest::notifyCursorLeaves(old, cur);
//LYXERR0("InsetMathScript::notifyCursorLeaves: 1 " << cur);
- // remove empty scripts if possible
- if (nargs() > 2) {
- // Case of two scripts. In this case, 1 = super, 2 = sub
- if (cur.idx() == 2 && cell(2).empty()) {
+ // Remove empty scripts if possible:
+
+ // The case of two scripts, but only one got empty (1 = super, 2 = sub).
+ // We keep the script inset, but remove the empty script.
+ if (nargs() > 2 && (!cell(1).empty() || !cell(2).empty())) {
+ if (cell(2).empty()) {
// must be a subscript...
- cur.recordUndoInset();
+ old.recordUndoInset();
removeScript(false);
+ cur.screenUpdateFlags(cur.result().screenUpdate() | Update::SinglePar);
return true;
- } else if (cur.idx() == 1 && cell(1).empty()) {
+ } else if (cell(1).empty()) {
// must be a superscript...
- cur.recordUndoInset();
+ old.recordUndoInset();
removeScript(true);
+ cur.screenUpdateFlags(cur.result().screenUpdate() | Update::SinglePar);
return true;
}
- } else if (nargs() > 1 && cur.idx() == 1 && cell(1).empty()) {
- // could be either subscript or super script
- cur.recordUndoInset();
- removeScript(cell_1_is_up_);
+ }
+ // Now the two suicide cases:
+ // * we have only one script which is empty
+ // * we have two scripts which are both empty.
+ // The script inset is removed completely.
+ if ((nargs() == 2 && cell(1).empty())
+ || (nargs() == 3 && cell(1).empty() && cell(2).empty())) {
+ // Make undo step. We cannot use cur for this because
+ // it does not necessarily point to us anymore. But we
+ // should be on top of the cursor old.
+ Cursor insetCur = old;
+ int scriptSlice = insetCur.find(this);
+ LASSERT(scriptSlice != -1, /**/);
+ insetCur.cutOff(scriptSlice);
+ insetCur.recordUndoInset();
+
// Let the script inset commit suicide. This is
// modelled on Cursor.pullArg(), but tries not to
// invoke notifyCursorLeaves again and does not touch
// cur (since the top slice will be deleted
- // afterwards))
+ // afterwards)
MathData ar = cell(0);
- Cursor tmpcur = cur;
- tmpcur.pop();
- tmpcur.cell().erase(tmpcur.pos());
- tmpcur.cell().insert(tmpcur.pos(), ar);
+ insetCur.pop();
+ insetCur.cell().erase(insetCur.pos());
+ insetCur.cell().insert(insetCur.pos(), ar);
+
+ // redraw
+ cur.screenUpdateFlags(cur.result().screenUpdate() | Update::SinglePar);
return true;
}
{
//LYXERR("InsetMathScript: request: " << cmd);
- if (cmd.action == LFUN_MATH_LIMITS) {
+ if (cmd.action() == LFUN_MATH_LIMITS) {
if (!cmd.argument().empty()) {
if (cmd.argument() == "limits")
limits_ = 1;
}
+// the idea for dual scripts came from the eLyXer code
+void InsetMathScript::validate(LaTeXFeatures & features) const
+{
+ if (features.runparams().math_flavor == OutputParams::MathAsHTML)
+ features.addPreambleSnippet("<style type=\"text/css\">\n"
+ "span.scripts{display: inline-block; vertical-align: middle; text-align:center; font-size: 75%;}\n"
+ "span.scripts span {display: block;}\n"
+ "sub.math{font-size: 75%;}\n"
+ "sup.math{font-size: 75%;}\n"
+ "</style>");
+ InsetMathNest::validate(features);
+}
+
} // namespace lyx