-/*
- * File: math_cursor.C
- * Purpose: Interaction for mathed
- * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
- * Created: January 1996
- * Description: Math interaction for a WYSIWYG math editor.
+/**
+ * \file math_cursor.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
*
- * Dependencies: Xlib, XForms
+ * \author Alejandro Aguilar Sierra
+ * \author André Pönitz
*
- * Copyright: 1996, Alejandro Aguilar Sierra
- *
- * Version: 0.8beta, Math & Lyx project.
- *
- * You are free to use and modify this code under the terms of
- * the GNU General Public Licence version 2 or later.
+ * Full author contact details are available in file CREDITS.
*/
#include <config.h>
-#include <lyxrc.h>
+#include <lyxrc.h>
-#include "support/lstrings.h"
#include "support/LAssert.h"
#include "support/limited_stack.h"
#include "debug.h"
-#include "frontends/Painter.h"
+#include "support/std_sstream.h"
#include "math_cursor.h"
#include "formulabase.h"
#include "funcrequest.h"
-#include "math_autocorrect.h"
#include "math_braceinset.h"
#include "math_commentinset.h"
#include "math_charinset.h"
-#include "math_extern.h"
#include "math_factory.h"
-#include "math_fontinset.h"
#include "math_gridinset.h"
-#include "math_iterator.h"
#include "math_macroarg.h"
#include "math_macrotemplate.h"
#include "math_mathmlstream.h"
#include "math_support.h"
#include "math_unknowninset.h"
-#include <algorithm>
-#include <cctype>
//#define FILEDEBUG 1
+using namespace lyx::support;
+
using std::endl;
using std::min;
using std::max;
void MathCursor::push(MathAtom & t)
{
- Cursor_.push_back(MathCursorPos(t.nucleus()));
+ Cursor_.push_back(CursorPos(t.nucleus()));
}
void MathCursor::pushLeft(MathAtom & t)
{
- //lyxerr << "Entering atom " << t << " left\n";
+ //lyxerr << "Entering atom " << t << " left" << endl;
push(t);
t->idxFirst(idx(), pos());
}
void MathCursor::pushRight(MathAtom & t)
{
- //lyxerr << "Entering atom " << t << " right\n";
+ //lyxerr << "Entering atom " << t << " right" << endl;
posLeft();
push(t);
t->idxLast(idx(), pos());
bool MathCursor::popLeft()
{
- //lyxerr << "Leaving atom to the left\n";
+ //lyxerr << "Leaving atom to the left" << endl;
if (depth() <= 1) {
if (depth() == 1)
- par()->notifyCursorLeaves(idx());
+ inset()->notifyCursorLeaves(idx());
return false;
}
- par()->notifyCursorLeaves(idx());
+ inset()->notifyCursorLeaves(idx());
Cursor_.pop_back();
return true;
}
bool MathCursor::popRight()
{
- //lyxerr << "Leaving atom "; par()->write(cerr, false); cerr << " right\n";
+ //lyxerr << "Leaving atom "; inset()->write(cerr, false); cerr << " right" << endl;
if (depth() <= 1) {
if (depth() == 1)
- par()->notifyCursorLeaves(idx());
+ inset()->notifyCursorLeaves(idx());
return false;
}
- par()->notifyCursorLeaves(idx());
+ inset()->notifyCursorLeaves(idx());
Cursor_.pop_back();
posRight();
return true;
bool MathCursor::isInside(MathInset const * p) const
{
for (unsigned i = 0; i < depth(); ++i)
- if (Cursor_[i].par_ == p)
+ if (Cursor_[i].inset_ == p)
return true;
return false;
}
// we can't move into anything new during selection
if (depth() == Anchor_.size())
return false;
- if (t.operator->() != Anchor_[depth()].par_)
+ if (t.operator->() != Anchor_[depth()].inset_)
return false;
}
return true;
bool MathCursor::inNucleus() const
{
- return par()->asScriptInset() && idx() == 2;
+ return inset()->asScriptInset() && idx() == 2;
}
{
Cursor_.clear();
push(formula_->par());
- par()->idxFirst(idx(), pos());
+ inset()->idxFirst(idx(), pos());
}
{
Cursor_.clear();
push(formula_->par());
- par()->idxLast(idx(), pos());
+ inset()->idxLast(idx(), pos());
}
// anchor might be deeper, should have same path then
for (MathIterator::size_type i = 0; i < cursor.size(); ++i)
- if (cursor[i].par_ != anchor[i].par_)
+ if (cursor[i].inset_ != anchor[i].inset_)
return false;
// position should be ok.
autocorrect_ = false;
selHandle(sel);
macroModeClose();
- if (!par()->idxHome(idx(), pos()))
+ if (!inset()->idxHome(idx(), pos()))
return popLeft();
dump("home 2");
targetx_ = -1; // "no target"
autocorrect_ = false;
selHandle(sel);
macroModeClose();
- if (!par()->idxEnd(idx(), pos()))
+ if (!inset()->idxEnd(idx(), pos()))
return popRight();
dump("end 2");
targetx_ = -1; // "no target"
void MathCursor::markInsert()
{
- //lyxerr << "inserting mark\n";
+ //lyxerr << "inserting mark" << endl;
array().insert(pos(), MathAtom(new MathCharInset(0)));
}
void MathCursor::markErase()
{
- //lyxerr << "deleting mark\n";
+ //lyxerr << "deleting mark" << endl;
array().erase(pos());
}
}
+void MathCursor::insert2(string const & str)
+{
+ MathArray ar;
+ asArray(str, ar);
+ insert(ar);
+}
+
+
void MathCursor::insert(string const & str)
{
- //lyxerr << "inserting '" << str << "'\n";
+ //lyxerr << "inserting '" << str << "'" << endl;
selClearOrDel();
for (string::const_iterator it = str.begin(); it != str.end(); ++it)
plainInsert(MathAtom(new MathCharInset(*it)));
void MathCursor::insert(char c)
{
- //lyxerr << "inserting '" << c << "'\n";
+ //lyxerr << "inserting '" << c << "'" << endl;
selClearOrDel();
plainInsert(MathAtom(new MathCharInset(c)));
}
void MathCursor::niceInsert(string const & t)
{
- MathArray ar = asArray(t);
+ MathArray ar;
+ asArray(t, ar);
if (ar.size() == 1)
niceInsert(ar[0]);
else
}
if (pos() == 0) {
- if (par()->ncols() == 1 &&
- par()->nrows() == 1 &&
+ if (inset()->ncols() == 1 &&
+ inset()->nrows() == 1 &&
depth() == 1 &&
size() == 0)
return false;
// delete empty cells if possible
if (array().empty())
- if (par()->idxDelete(idx()))
+ if (inset()->idxDelete(idx()))
return true;
// old behaviour when in last position of cell
if (pos() == size()) {
- if (par()->ncols() == 1 && par()->nrows() == 1 && depth() == 1 && size() == 0)
+ if (inset()->ncols() == 1 && inset()->nrows() == 1 && depth() == 1 && size() == 0)
return false;
else{
- par()->idxGlue(idx());
+ inset()->idxGlue(idx());
return true;
}
}
if (s == "\\")
return;
- string name = s.substr(1);
+ string const name = s.substr(1);
// prevent entering of recursive macros
- if (formula()->lyxCode() == Inset::MATHMACRO_CODE
+ if (formula()->lyxCode() == InsetOld::MATHMACRO_CODE
&& formula()->getInsetName() == name)
- lyxerr << "can't enter recursive macro\n";
+ lyxerr << "can't enter recursive macro" << endl;
niceInsert(createMathInset(name));
}
}
-void MathCursor::selPaste(int n)
+void MathCursor::selPaste(size_t n)
{
dump("selPaste");
selClearOrDel();
{
if (!selection_)
return;
- MathCursorPos i1;
- MathCursorPos i2;
+ CursorPos i1;
+ CursorPos i2;
getSelection(i1, i2);
- i1.par_->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_);
+ i1.inset_->drawSelection(pi, i1.idx_, i1.pos_, i2.idx_, i2.pos_);
}
void MathCursor::handleNest(MathAtom const & a)
{
MathAtom at = a;
- at.nucleus()->cell(0) = asArray(grabAndEraseSelection());
+ asArray(grabAndEraseSelection(), at.nucleus()->cell(0));
insert(at);
pushRight(prevAtom());
}
void MathCursor::getPos(int & x, int & y) const
{
- par()->getPos(idx(), pos(), x, y);
+ inset()->getPos(idx(), pos(), x, y);
}
}
-MathInset * MathCursor::par() const
+MathInset * MathCursor::inset() const
{
- return cursor().par_;
+ return cursor().inset_;
}
MathGridInset * MathCursor::enclosingGrid(MathCursor::idx_type & idx) const
{
for (MathInset::difference_type i = depth() - 1; i >= 0; --i) {
- MathGridInset * p = Cursor_[i].par_->asGridInset();
+ MathGridInset * p = Cursor_[i].inset_->asGridInset();
if (p) {
idx = Cursor_[i].idx_;
return p;
void MathCursor::popToHere(MathInset const * p)
{
- while (depth() && Cursor_.back().par_ != p)
+ while (depth() && Cursor_.back().inset_ != p)
Cursor_.pop_back();
}
void MathCursor::popToEnclosingGrid()
{
- while (depth() && !Cursor_.back().par_->asGridInset())
+ while (depth() && !Cursor_.back().inset_->asGridInset())
Cursor_.pop_back();
}
void MathCursor::popToEnclosingHull()
{
- while (depth() && !Cursor_.back().par_->asHullInset())
+ while (depth() && !Cursor_.back().inset_->asHullInset())
Cursor_.pop_back();
}
void MathCursor::normalize()
{
- if (idx() >= par()->nargs()) {
+ if (idx() >= inset()->nargs()) {
lyxerr << "this should not really happen - 1: "
- << idx() << ' ' << par()->nargs()
- << " in: " << par() << endl;
+ << idx() << ' ' << inset()->nargs()
+ << " in: " << inset() << endl;
dump("error 2");
}
- idx() = min(idx(), par()->nargs() - 1);
+ idx() = min(idx(), inset()->nargs() - 1);
if (pos() > size()) {
lyxerr << "this should not really happen - 2: "
<< pos() << ' ' << size() << " in idx: " << idx()
<< " in atom: '";
WriteStream wi(lyxerr, false, true);
- par()->write(wi);
+ inset()->write(wi);
lyxerr << endl;
dump("error 4");
}
MathAtom const & MathCursor::prevAtom() const
{
- lyx::Assert(pos() > 0);
+ Assert(pos() > 0);
return array()[pos() - 1];
}
MathAtom & MathCursor::prevAtom()
{
- lyx::Assert(pos() > 0);
+ Assert(pos() > 0);
return array()[pos() - 1];
}
MathAtom const & MathCursor::nextAtom() const
{
- lyx::Assert(pos() < size());
+ Assert(pos() < size());
return array()[pos()];
}
MathAtom & MathCursor::nextAtom()
{
- lyx::Assert(pos() < size());
+ Assert(pos() < size());
return array()[pos()];
}
{
static MathArray dummy;
- if (idx() >= par()->nargs()) {
- lyxerr << "############ idx_ " << idx() << " not valid\n";
+ if (idx() >= inset()->nargs()) {
+ lyxerr << "############ idx_ " << idx() << " not valid" << endl;
return dummy;
}
if (depth() == 0) {
- lyxerr << "############ depth() == 0 not valid\n";
+ lyxerr << "############ depth() == 0 not valid" << endl;
return dummy;
}
void MathCursor::idxNext()
{
- par()->idxNext(idx(), pos());
+ inset()->idxNext(idx(), pos());
}
void MathCursor::idxPrev()
{
- par()->idxPrev(idx(), pos());
+ inset()->idxPrev(idx(), pos());
}
}
-void MathCursor::getSelection(MathCursorPos & i1, MathCursorPos & i2) const
+void MathCursor::getSelection(CursorPos & i1, CursorPos & i2) const
{
- MathCursorPos anc = normalAnchor();
+ CursorPos anc = normalAnchor();
if (anc < cursor()) {
i1 = anc;
i2 = cursor();
}
-MathCursorPos & MathCursor::cursor()
+CursorPos & MathCursor::cursor()
{
- lyx::Assert(depth());
+ Assert(depth());
return Cursor_.back();
}
-MathCursorPos const & MathCursor::cursor() const
+CursorPos const & MathCursor::cursor() const
{
- lyx::Assert(depth());
+ Assert(depth());
return Cursor_.back();
}
push(nextAtom());
idx() = up; // the superscript has index 1
pos() = size();
- ///lyxerr << "updown: handled by scriptinset to the left\n";
+ ///lyxerr << "updown: handled by scriptinset to the left" << endl;
return true;
}
}
push(nextAtom());
idx() = up;
pos() = 0;
- ///lyxerr << "updown: handled by scriptinset to the right\n";
+ ///lyxerr << "updown: handled by scriptinset to the right" << endl;
return true;
}
}
// try current cell for e.g. text insets
- if (par()->idxUpDown2(idx(), pos(), up, targetx_))
+ if (inset()->idxUpDown2(idx(), pos(), up, targetx_))
return true;
//xarray().boundingBox(xlow, xhigh, ylow, yhigh);
//else
// ylow = yo + 4;
//if (bruteFind(xo, yo, xlow, xhigh, ylow, yhigh)) {
- // lyxerr << "updown: handled by brute find in the same cell\n";
+ // lyxerr << "updown: handled by brute find in the same cell" << endl;
// return true;
//}
// try to find an inset that knows better then we
while (1) {
- ///lyxerr << "updown: We are in " << *par() << " idx: " << idx() << '\n';
+ ///lyxerr << "updown: We are in " << *inset() << " idx: " << idx() << endl;
// ask inset first
- if (par()->idxUpDown(idx(), pos(), up, targetx_)) {
+ if (inset()->idxUpDown(idx(), pos(), up, targetx_)) {
// try to find best position within this inset
if (!selection())
bruteFind2(xo, yo);
}
// no such inset found, just take something "above"
- ///lyxerr << "updown: handled by strange case\n";
+ ///lyxerr << "updown: handled by strange case" << endl;
if (!popLeft())
return
bruteFind(xo, yo,
bool MathCursor::idxLineLast()
{
- idx() -= idx() % par()->ncols();
- idx() += par()->ncols() - 1;
+ idx() -= idx() % inset()->ncols();
+ idx() += inset()->ncols() - 1;
pos() = size();
return true;
}
bool MathCursor::idxLeft()
{
- return par()->idxLeft(idx(), pos());
+ return inset()->idxLeft(idx(), pos());
}
bool MathCursor::idxRight()
{
- return par()->idxRight(idx(), pos());
+ return inset()->idxRight(idx(), pos());
}
string safe = grabAndEraseSelection();
if (inNucleus()) {
// we are in a nucleus of a script inset, move to _our_ script
- par()->asScriptInset()->ensure(up);
+ inset()->asScriptInset()->ensure(up);
idx() = up;
pos() = 0;
} else if (hasPrevAtom() && prevAtom()->asScriptInset()) {
bool MathCursor::interpret(char c)
{
- //lyxerr << "interpret 2: '" << c << "'\n";
+ //lyxerr << "interpret 2: '" << c << "'" << endl;
targetx_ = -1; // "no target"
if (inMacroArgMode()) {
--pos();
// handle macroMode
if (inMacroMode()) {
string name = macroName();
- //lyxerr << "interpret name: '" << name << "'\n";
+ //lyxerr << "interpret name: '" << name << "'" << endl;
if (isalpha(c)) {
activeMacro()->setName(activeMacro()->name() + c);
selClearOrDel();
if (c == '\\') {
- //lyxerr << "starting with macro\n";
+ //lyxerr << "starting with macro" << endl;
insert(MathAtom(new MathUnknownInset("\\", false)));
return true;
}
ostringstream os;
os << "Math editor mode. ";
for (int i = 0, n = depth(); i < n; ++i) {
- Cursor_[i].par_->infoize(os);
+ Cursor_[i].inset_->infoize(os);
os << " ";
}
if (hasPrevAtom())
namespace {
-void region(MathCursorPos const & i1, MathCursorPos const & i2,
+void region(CursorPos const & i1, CursorPos const & i2,
MathInset::row_type & r1, MathInset::row_type & r2,
MathInset::col_type & c1, MathInset::col_type & c2)
{
- MathInset * p = i1.par_;
+ MathInset * p = i1.inset_;
c1 = p->col(i1.idx_);
c2 = p->col(i2.idx_);
if (c1 > c2)
if (!selection_)
return string();
- MathCursorPos i1;
- MathCursorPos i2;
+ CursorPos i1;
+ CursorPos i2;
getSelection(i1, i2);
if (i1.idx_ == i2.idx_) {
for (col_type col = c1; col <= c2; ++col) {
if (col > c1)
data += '&';
- data += asString(i1.par_->cell(i1.par_->index(row, col)));
+ data += asString(i1.inset_->cell(i1.inset_->index(row, col)));
}
}
return data;
void MathCursor::eraseSelection()
{
- MathCursorPos i1;
- MathCursorPos i2;
+ CursorPos i1;
+ CursorPos i2;
getSelection(i1, i2);
if (i1.idx_ == i2.idx_)
i1.cell().erase(i1.pos_, i2.pos_);
else {
- MathInset * p = i1.par_;
+ MathInset * p = i1.inset_;
row_type r1, r2;
col_type c1, c2;
region(i1, i2, r1, r2, c1, c2);
}
-MathCursorPos MathCursor::normalAnchor() const
+CursorPos MathCursor::normalAnchor() const
{
if (Anchor_.size() < depth()) {
Anchor_ = Cursor_;
- lyxerr << "unusual Anchor size\n";
+ lyxerr << "unusual Anchor size" << endl;
}
//lyx::Assert(Anchor_.size() >= cursor.depth());
// use Anchor on the same level as Cursor
- MathCursorPos normal = Anchor_[depth() - 1];
+ CursorPos normal = Anchor_[depth() - 1];
if (depth() < Anchor_.size() && !(normal < cursor())) {
// anchor is behind cursor -> move anchor behind the inset
++normal.pos_;
dispatch_result MathCursor::dispatch(FuncRequest const & cmd)
{
- // mouse clicks are somewhat special
+ // mouse clicks are somewhat special
// check
switch (cmd.action) {
case LFUN_MOUSE_PRESS:
case LFUN_MOUSE_MOTION:
case LFUN_MOUSE_RELEASE:
case LFUN_MOUSE_DOUBLE: {
- MathCursorPos & pos = Cursor_.back();
+ CursorPos & pos = Cursor_.back();
dispatch_result res = UNDISPATCHED;
int x = 0, y = 0;
getPos(x, y);
}
for (int i = Cursor_.size() - 1; i >= 0; --i) {
- MathCursorPos & pos = Cursor_[i];
- dispatch_result res = pos.par_->dispatch(cmd, pos.idx_, pos.pos_);
+ CursorPos & pos = Cursor_[i];
+ dispatch_result res = pos.inset_->dispatch(cmd, pos.idx_, pos.pos_);
if (res != UNDISPATCHED) {
if (res == DISPATCHED_POP) {
Cursor_.shrink(i + 1);
MathInset::mode_type MathCursor::currentMode() const
{
for (int i = Cursor_.size() - 1; i >= 0; --i) {
- MathInset::mode_type res = Cursor_[i].par_->currentMode();
+ MathInset::mode_type res = Cursor_[i].inset_->currentMode();
if (res != MathInset::UNDECIDED_MODE)
return res;
}
{
if (mathcursor) {
InsetFormulaBase * f = mathcursor->formula();
- f->hideInsetCursor(bv);
delete mathcursor;
mathcursor = 0;
f->insetUnlock(bv);