lyx_mirror/src/mathed/InsetMathNest.C

1411 lines
34 KiB
C++
Raw Normal View History

/**
* \file InsetMathNest.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Andr<EFBFBD> P<EFBFBD>nitz
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetMathNest.h"
#include "InsetMathArray.h"
#include "InsetMathBig.h"
#include "InsetMathBox.h"
#include "InsetMathBrace.h"
#include "InsetMathColor.h"
#include "InsetMathComment.h"
#include "MathData.h"
#include "InsetMathDelim.h"
#include "MathFactory.h"
#include "InsetMathHull.h"
#include "MathMLStream.h"
#include "MathMacroArgument.h"
//#include "InsetMathMBox.h"
#include "MathParser.h"
#include "InsetMathScript.h"
#include "InsetMathSpace.h"
#include "InsetMathSymbol.h"
#include "MathSupport.h"
#include "InsetMathUnknown.h"
#include "InsetMathRef.h"
#include "BufferView.h"
#include "CutAndPaste.h"
#include "FuncStatus.h"
#include "LColor.h"
#include "bufferview_funcs.h"
#include "coordcache.h"
#include "cursor.h"
#include "debug.h"
#include "dispatchresult.h"
#include "funcrequest.h"
#include "gettext.h"
#include "outputparams.h"
#include "undo.h"
#include "support/lstrings.h"
#include "frontends/Painter.h"
Split clipboard and X selection * src/LyXAction.C (LyXAction::init): handle new LFUN_CLIPBOARD_PASTE * src/insets/insettabular.C (InsetTabular::doDispatch): ditto * src/insets/insetbox.C (InsetBox::doDispatch): ditto * src/insets/insetert.C (InsetERT::doDispatch): ditto (InsetERT::getStatus): ditto * src/insets/insetcharstyle.C (InsetCharStyle::doDispatch): ditto * src/BufferView_pimpl.C (BufferView::Pimpl::selectionRequest): stuff selection, not clipboard * src/mathed/math_nestinset.C (MathNestInset::lfunMousePress): get stuff selection, not clipboard (MathNestInset::lfunMouseRelease): clipboard -> selection in commented code * src/CutAndPaste.C (cutSelection): ditto * src/frontends/{qt3,gtk}/GuiImplementation.C (GuiImplementation::newWorkArea): create new selection, not clipboard, since the clipboard is now an object (GuiImplementation::destroyWorkArea): destroy selection, not clipboard * src/frontends/{qt4,qt3,gtk}/GuiSelection.h: new, copied from GuiClipboard.h * src/frontends/{qt4,qt3,gtk}/GuiSelection.C: new, copied from GuiClipboard.C * src/frontends/{qt3,gtk}/GuiImplementation.h (selection): new accessor for selection_ (selection_): new, the global selection object * src/frontends/{qt4,qt3,gtk}/Makefile.am: add GuiSelection.C and GuiSelection.h * src/frontends/{qt4,qt3,gtk}/GuiClipboard.C (GuiClipboard::get): return clipboard, not selection (GuiClipboard::put): stuff clipboard, not selection * src/frontends/{qt4,qt3,gtk}/GuiClipboard.h (haveSelection): remove (this is now in GuiSelection) * src/frontends/{qt3,gtk}/GuiClipboard.h (old_work_area_): remove, since it is not needed anymore * src/frontends/gtk/ghelpers.C (getGTKStockIcon): handle LFUN_CLIPBOARD_PASTE * src/frontends/Clipboard.h (haveSelection): remove (this is now in Selection) * src/frontends/qt4/GuiImplementation.[Ch] (GuiImplementation::selection): new accessor for selection_ * src/frontends/Gui.h (selection): New accessor for the global selection object * src/frontends/Selection.h; new, copied from Clipboard.h * src/frontends/Makefile.am: add Selection.h * src/text3.C (various): s/clipboard().haveSelection/selection().haveSelection/ (LyXText::dispatch): handle LFUN_CLIPBOARD_PASTE (LyXText::getStatus): ditto * src/lfuns.h: new lfun LFUN_CLIPBOARD_PASTE * lib/ui/stdmenus.ui: add new lfun LFUN_CLIPBOARD_PASTE git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@14408 a592a061-630c-0410-9148-cb99ea01b6c8
2006-07-10 11:32:25 +00:00
#include "frontends/Selection.h"
#include "frontends/nullpainter.h"
#include "funcrequest.h"
#include "lyxserver.h"
#include "lyxsocket.h"
#include <sstream>
using lyx::docstring;
using lyx::cap::copySelection;
using lyx::cap::grabAndEraseSelection;
using lyx::cap::cutSelection;
using lyx::cap::replaceSelection;
using lyx::cap::selClearOrDel;
using std::endl;
using std::string;
using std::istringstream;
InsetMathNest::InsetMathNest(idx_type nargs)
: cells_(nargs), lock_(false)
{}
InsetMath::idx_type InsetMathNest::nargs() const
{
return cells_.size();
}
MathArray & InsetMathNest::cell(idx_type i)
{
return cells_[i];
}
MathArray const & InsetMathNest::cell(idx_type i) const
{
return cells_[i];
}
void InsetMathNest::cursorPos(CursorSlice const & sl, bool /*boundary*/,
int & x, int & y) const
{
// FIXME: This is a hack. Ideally, the coord cache should not store
// absolute positions, but relative ones. This would mean to call
// setXY() not in MathArray::draw(), but in the parent insets' draw()
// with the correctly adjusted x,y values. But this means that we'd have
// to touch all (math)inset's draw() methods. Right now, we'll store
// absolute value, and make them here relative, only to make them
// absolute again when actually drawing the cursor. What a mess.
BOOST_ASSERT(ptr_cmp(&sl.inset(), this));
MathArray const & ar = sl.cell();
if (!theCoords.getArrays().has(&ar)) {
// this can (semi-)legally happen if we just created this cell
// and it never has been drawn before. So don't ASSERT.
//lyxerr << "no cached data for array " << &ar << endl;
x = 0;
y = 0;
return;
}
Point const pt = theCoords.getArrays().xy(&ar);
if (!theCoords.getInsets().has(this)) {
// same as above
//lyxerr << "no cached data for inset " << this << endl;
x = 0;
y = 0;
return;
}
Point const pt2 = theCoords.getInsets().xy(this);
//lyxerr << "retrieving position cache for MathArray "
// << pt.x_ << ' ' << pt.y_ << std::endl;
x = pt.x_ - pt2.x_ + ar.pos2x(sl.pos());
y = pt.y_ - pt2.y_;
// lyxerr << "pt.y_ : " << pt.y_ << " pt2_.y_ : " << pt2.y_
// << " asc: " << ascent() << " des: " << descent()
// << " ar.asc: " << ar.ascent() << " ar.des: " << ar.descent() << endl;
// move cursor visually into empty cells ("blue rectangles");
if (ar.empty())
x += 2;
}
void InsetMathNest::metrics(MetricsInfo const & mi) const
{
MetricsInfo m = mi;
for (idx_type i = 0, n = nargs(); i != n; ++i)
cell(i).metrics(m);
}
bool InsetMathNest::idxNext(LCursor & cur) const
{
BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
if (cur.idx() == cur.lastidx())
return false;
++cur.idx();
cur.pos() = 0;
return true;
}
bool InsetMathNest::idxRight(LCursor & cur) const
{
return idxNext(cur);
}
bool InsetMathNest::idxPrev(LCursor & cur) const
{
BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
if (cur.idx() == 0)
return false;
--cur.idx();
cur.pos() = cur.lastpos();
return true;
}
bool InsetMathNest::idxLeft(LCursor & cur) const
{
return idxPrev(cur);
}
bool InsetMathNest::idxFirst(LCursor & cur) const
{
BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
if (nargs() == 0)
return false;
cur.idx() = 0;
cur.pos() = 0;
return true;
}
bool InsetMathNest::idxLast(LCursor & cur) const
{
BOOST_ASSERT(ptr_cmp(&cur.inset(), this));
if (nargs() == 0)
return false;
cur.idx() = cur.lastidx();
cur.pos() = cur.lastpos();
return true;
}
void InsetMathNest::dump() const
{
WriteStream os(lyxerr);
os << "---------------------------------------------\n";
write(os);
os << "\n";
for (idx_type i = 0, n = nargs(); i != n; ++i)
os << cell(i) << "\n";
os << "---------------------------------------------\n";
}
void InsetMathNest::draw(PainterInfo & pi, int x, int y) const
{
#if 0
if (lock_)
pi.pain.fillRectangle(x, y - ascent(), width(), height(),
LColor::mathlockbg);
#endif
setPosCache(pi, x, y);
}
void InsetMathNest::drawSelection(PainterInfo & pi, int x, int y) const
{
// this should use the x/y values given, not the cached values
LCursor & cur = pi.base.bv->cursor();
if (!cur.selection())
return;
if (!ptr_cmp(&cur.inset(), this))
return;
// FIXME: hack to get position cache warm
static lyx::frontend::NullPainter nop;
PainterInfo pinop(pi);
pinop.pain = nop;
draw(pinop, x, y);
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
CursorSlice s1 = cur.selBegin();
CursorSlice s2 = cur.selEnd();
//lyxerr << "InsetMathNest::drawing selection: "
// << " s1: " << s1 << " s2: " << s2 << endl;
if (s1.idx() == s2.idx()) {
MathArray const & c = cell(s1.idx());
int x1 = c.xo() + c.pos2x(s1.pos());
int y1 = c.yo() - c.ascent();
int x2 = c.xo() + c.pos2x(s2.pos());
int y2 = c.yo() + c.descent();
pi.pain.fillRectangle(x1, y1, x2 - x1, y2 - y1, LColor::selection);
//lyxerr << "InsetMathNest::drawing selection 3: "
// << " x1: " << x1 << " x2: " << x2
// << " y1: " << y1 << " y2: " << y2 << endl;
} else {
for (idx_type i = 0; i < nargs(); ++i) {
if (idxBetween(i, s1.idx(), s2.idx())) {
MathArray const & c = cell(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 InsetMathNest::validate(LaTeXFeatures & features) const
{
for (idx_type i = 0; i < nargs(); ++i)
cell(i).validate(features);
}
void InsetMathNest::replace(ReplaceData & rep)
{
for (idx_type i = 0; i < nargs(); ++i)
cell(i).replace(rep);
}
bool InsetMathNest::contains(MathArray const & ar) const
{
for (idx_type i = 0; i < nargs(); ++i)
if (cell(i).contains(ar))
return true;
return false;
}
bool InsetMathNest::lock() const
{
return lock_;
}
void InsetMathNest::lock(bool l)
{
lock_ = l;
}
bool InsetMathNest::isActive() const
{
return nargs() > 0;
}
MathArray InsetMathNest::glue() const
{
MathArray ar;
for (size_t i = 0; i < nargs(); ++i)
ar.append(cell(i));
return ar;
}
void InsetMathNest::write(WriteStream & os) const
{
os << '\\' << name().c_str();
for (size_t i = 0; i < nargs(); ++i)
os << '{' << cell(i) << '}';
if (nargs() == 0)
os.pendingSpace(true);
if (lock_ && !os.latex()) {
os << "\\lyxlock";
os.pendingSpace(true);
}
}
void InsetMathNest::normalize(NormalStream & os) const
{
os << '[' << name().c_str();
for (size_t i = 0; i < nargs(); ++i)
os << ' ' << cell(i);
os << ']';
}
int InsetMathNest::latex(Buffer const &, std::ostream & os,
OutputParams const & runparams) const
{
WriteStream wi(os, runparams.moving_arg, true);
write(wi);
return wi.line();
}
bool InsetMathNest::notifyCursorLeaves(LCursor & /*cur*/)
{
#ifdef WITH_WARNINGS
#warning look here
#endif
#if 0
MathArray & ar = cur.cell();
// remove base-only "scripts"
for (pos_type i = 0; i + 1 < ar.size(); ++i) {
InsetMathScript * p = operator[](i).nucleus()->asScriptInset();
if (p && p->nargs() == 1) {
MathArray ar = p->nuc();
erase(i);
insert(i, ar);
cur.adjust(i, ar.size() - 1);
}
}
// glue adjacent font insets of the same kind
for (pos_type i = 0; i + 1 < size(); ++i) {
InsetMathFont * p = operator[](i).nucleus()->asFontInset();
InsetMathFont const * q = operator[](i + 1)->asFontInset();
if (p && q && p->name() == q->name()) {
p->cell(0).append(q->cell(0));
erase(i + 1);
cur.adjust(i, -1);
}
}
#endif
return false;
}
void InsetMathNest::handleFont
(LCursor & cur, string const & arg, string const & font)
{
// this whole function is a hack and won't work for incremental font
// changes...
recordUndo(cur, Undo::ATOMIC);
if (cur.inset().asInsetMath()->name() == font)
cur.handleFont(font);
else {
cur.handleNest(createInsetMath(font));
cur.insert(arg);
}
}
void InsetMathNest::handleFont2(LCursor & cur, string const & arg)
{
recordUndo(cur, Undo::ATOMIC);
LyXFont font;
bool b;
bv_funcs::string2font(arg, font, b);
if (font.color() != LColor::inherit) {
MathAtom at = MathAtom(new InsetMathColor(true, font.color()));
cur.handleNest(at, 0);
}
}
void InsetMathNest::doDispatch(LCursor & cur, FuncRequest & cmd)
{
//lyxerr << "InsetMathNest: request: " << cmd << std::endl;
//CursorSlice sl = cur.current();
switch (cmd.action) {
case LFUN_PASTE: {
recordUndo(cur);
cur.message(_("Paste"));
replaceSelection(cur);
size_t n = 0;
istringstream is(lyx::to_utf8(cmd.argument()));
is >> n;
docstring const selection = lyx::cap::getSelection(cur.buffer(), n);
// FIXME UNICODE
cur.niceInsert(lyx::to_utf8(selection));
cur.clearSelection(); // bug 393
cur.bv().switchKeyMap();
finishUndo();
break;
}
case LFUN_CUT:
recordUndo(cur);
cutSelection(cur, true, true);
cur.message(_("Cut"));
// Prevent stale position >= size crash
// Probably not necessary anymore, see eraseSelection (gb 2005-10-09)
cur.normalize();
break;
case LFUN_COPY:
copySelection(cur);
// FIXME UNICODE
cur.message(_("Copy"));
break;
case LFUN_MOUSE_PRESS:
lfunMousePress(cur, cmd);
break;
case LFUN_MOUSE_MOTION:
lfunMouseMotion(cur, cmd);
break;
case LFUN_MOUSE_RELEASE:
lfunMouseRelease(cur, cmd);
break;
case LFUN_FINISHED_LEFT:
cur.bv().cursor() = cur;
break;
case LFUN_FINISHED_RIGHT:
++cur.pos();
cur.bv().cursor() = cur;
break;
case LFUN_FINISHED_UP:
cur.bv().cursor() = cur;
break;
case LFUN_FINISHED_DOWN:
++cur.pos();
cur.bv().cursor() = cur;
break;
case LFUN_CHAR_FORWARD_SELECT:
case LFUN_CHAR_FORWARD:
cur.selHandle(cmd.action == LFUN_CHAR_FORWARD_SELECT);
cur.autocorrect() = false;
cur.clearTargetX();
cur.macroModeClose();
if (cur.pos() != cur.lastpos() && cur.openable(cur.nextAtom())) {
cur.pushLeft(*cur.nextAtom().nucleus());
cur.inset().idxFirst(cur);
} else if (cur.posRight() || idxRight(cur)
|| cur.popRight() || cur.selection())
;
else {
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
cur.undispatched();
}
break;
case LFUN_CHAR_BACKWARD_SELECT:
case LFUN_CHAR_BACKWARD:
cur.selHandle(cmd.action == LFUN_CHAR_BACKWARD_SELECT);
cur.autocorrect() = false;
cur.clearTargetX();
cur.macroModeClose();
if (cur.pos() != 0 && cur.openable(cur.prevAtom())) {
cur.posLeft();
cur.push(*cur.nextAtom().nucleus());
cur.inset().idxLast(cur);
} else if (cur.posLeft() || idxLeft(cur)
|| cur.popLeft() || cur.selection())
;
else {
cmd = FuncRequest(LFUN_FINISHED_LEFT);
cur.undispatched();
}
break;
case LFUN_UP_SELECT:
case LFUN_UP:
// FIXME Tried to use clearTargetX and macroModeClose, crashed on cur.up()
if (cur.inMacroMode()) {
// Make Helge happy
cur.macroModeClose();
break;
}
cur.selHandle(cmd.action == LFUN_UP_SELECT);
if (!cur.up()) {
cmd = FuncRequest(LFUN_FINISHED_UP);
cur.undispatched();
}
// fixes bug 1598. Please check!
cur.normalize();
break;
case LFUN_DOWN_SELECT:
case LFUN_DOWN:
if (cur.inMacroMode()) {
cur.macroModeClose();
break;
}
cur.selHandle(cmd.action == LFUN_DOWN_SELECT);
if (!cur.down()) {
cmd = FuncRequest(LFUN_FINISHED_DOWN);
cur.undispatched();
}
// fixes bug 1598. Please check!
cur.normalize();
break;
case LFUN_MOUSE_DOUBLE:
case LFUN_MOUSE_TRIPLE:
case LFUN_WORD_SELECT:
cur.pos() = 0;
cur.idx() = 0;
cur.resetAnchor();
cur.selection() = true;
cur.pos() = cur.lastpos();
cur.idx() = cur.lastidx();
break;
case LFUN_PARAGRAPH_UP_SELECT:
case LFUN_PARAGRAPH_UP:
case LFUN_PARAGRAPH_DOWN_SELECT:
case LFUN_PARAGRAPH_DOWN:
break;
case LFUN_LINE_BEGIN_SELECT:
case LFUN_LINE_BEGIN:
case LFUN_WORD_BACKWARD_SELECT:
case LFUN_WORD_BACKWARD:
cur.selHandle(cmd.action == LFUN_WORD_BACKWARD_SELECT ||
cmd.action == LFUN_LINE_BEGIN_SELECT);
cur.macroModeClose();
if (cur.pos() != 0) {
cur.pos() = 0;
} else if (cur.col() != 0) {
cur.idx() -= cur.col();
cur.pos() = 0;
} else if (cur.idx() != 0) {
cur.idx() = 0;
cur.pos() = 0;
} else {
cmd = FuncRequest(LFUN_FINISHED_LEFT);
cur.undispatched();
}
break;
case LFUN_WORD_FORWARD_SELECT:
case LFUN_WORD_FORWARD:
case LFUN_LINE_END_SELECT:
case LFUN_LINE_END:
cur.selHandle(cmd.action == LFUN_WORD_FORWARD_SELECT ||
cmd.action == LFUN_LINE_END_SELECT);
cur.macroModeClose();
cur.clearTargetX();
if (cur.pos() != cur.lastpos()) {
cur.pos() = cur.lastpos();
} else if (ncols() && (cur.col() != cur.lastcol())) {
cur.idx() = cur.idx() - cur.col() + cur.lastcol();
cur.pos() = cur.lastpos();
} else if (cur.idx() != cur.lastidx()) {
cur.idx() = cur.lastidx();
cur.pos() = cur.lastpos();
} else {
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
cur.undispatched();
}
break;
case LFUN_SCREEN_UP_SELECT:
case LFUN_SCREEN_UP:
cmd = FuncRequest(LFUN_FINISHED_LEFT);
cur.undispatched();
break;
case LFUN_SCREEN_DOWN_SELECT:
case LFUN_SCREEN_DOWN:
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
cur.undispatched();
break;
case LFUN_CELL_FORWARD:
cur.inset().idxNext(cur);
break;
case LFUN_CELL_BACKWARD:
cur.inset().idxPrev(cur);
break;
case LFUN_WORD_DELETE_BACKWARD:
case LFUN_CHAR_DELETE_BACKWARD:
if (cur.pos() == 0)
// May affect external cell:
recordUndoInset(cur, Undo::ATOMIC);
else
recordUndo(cur, Undo::ATOMIC);
cur.backspace();
break;
case LFUN_WORD_DELETE_FORWARD:
case LFUN_CHAR_DELETE_FORWARD:
if (cur.pos() == cur.lastpos())
// May affect external cell:
recordUndoInset(cur, Undo::ATOMIC);
else
recordUndo(cur, Undo::ATOMIC);
cur.erase();
break;
case LFUN_ESCAPE:
if (cur.selection())
cur.clearSelection();
else {
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
cur.undispatched();
}
break;
case LFUN_INSET_TOGGLE:
recordUndo(cur);
lock(!lock());
cur.popRight();
break;
case LFUN_SELF_INSERT:
if (cmd.argument().size() != 1) {
recordUndo(cur);
string const arg = lyx::to_utf8(cmd.argument());
if (!interpret(cur, arg))
cur.insert(arg);
break;
}
// Don't record undo steps if we are in macro mode and
// cmd.argument is the next character of the macro name.
// Otherwise we'll get an invalid cursor if we undo after
// the macro was finished and the macro is a known command,
// e.g. sqrt. LCursor::macroModeClose replaces in this case
// the InsetMathUnknown with name "frac" by an empty
// InsetMathFrac -> a pos value > 0 is invalid.
// A side effect is that an undo before the macro is finished
// undoes the complete macro, not only the last character.
if (!cur.inMacroMode())
recordUndo(cur);
// spacial handling of space. If we insert an inset
// via macro mode, we want to put the cursor inside it
// if relevant. Think typing "\frac<space>".
if (cmd.argument()[0] == ' '
&& cur.inMacroMode() && cur.macroName() != "\\"
&& cur.macroModeClose()) {
MathAtom const atom = cur.prevAtom();
if (atom->asNestInset() && atom->nargs() > 0) {
cur.posLeft();
cur.pushLeft(*cur.nextInset());
}
// FIXME: Change to
// } else if (!interpret(cur, cmd.argument()[0])) {
// when interpret accepts UCS4 characters
} else if (!interpret(cur, lyx::to_utf8(cmd.argument()))) {
cmd = FuncRequest(LFUN_FINISHED_RIGHT);
cur.undispatched();
}
break;
//case LFUN_SERVER_GET_XY:
// sprintf(dispatch_buffer, "%d %d",);
// break;
case LFUN_SERVER_SET_XY: {
lyxerr << "LFUN_SERVER_SET_XY broken!" << endl;
int x = 0;
int y = 0;
istringstream is(lyx::to_utf8(cmd.argument()));
is >> x >> y;
cur.setScreenPos(x, y);
break;
}
// Special casing for superscript in case of LyX handling
// dead-keys:
case LFUN_ACCENT_CIRCUMFLEX:
if (cmd.argument().empty()) {
// do superscript if LyX handles
// deadkeys
recordUndo(cur, Undo::ATOMIC);
script(cur, true, grabAndEraseSelection(cur));
}
break;
case LFUN_ACCENT_UMLAUT:
case LFUN_ACCENT_ACUTE:
case LFUN_ACCENT_GRAVE:
case LFUN_ACCENT_BREVE:
case LFUN_ACCENT_DOT:
case LFUN_ACCENT_MACRON:
case LFUN_ACCENT_CARON:
case LFUN_ACCENT_TILDE:
case LFUN_ACCENT_CEDILLA:
case LFUN_ACCENT_CIRCLE:
case LFUN_ACCENT_UNDERDOT:
case LFUN_ACCENT_TIE:
case LFUN_ACCENT_OGONEK:
case LFUN_ACCENT_HUNGARIAN_UMLAUT:
break;
// Math fonts
case LFUN_FONT_FREE_APPLY:
case LFUN_FONT_FREE_UPDATE:
handleFont2(cur, lyx::to_utf8(cmd.argument()));
break;
case LFUN_FONT_BOLD:
if (currentMode() == TEXT_MODE)
handleFont(cur, lyx::to_utf8(cmd.argument()), "textbf");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathbf");
break;
case LFUN_FONT_SANS:
if (currentMode() == TEXT_MODE)
handleFont(cur, lyx::to_utf8(cmd.argument()), "textsf");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathsf");
break;
case LFUN_FONT_EMPH:
if (currentMode() == TEXT_MODE)
handleFont(cur, lyx::to_utf8(cmd.argument()), "emph");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathcal");
break;
case LFUN_FONT_ROMAN:
if (currentMode() == TEXT_MODE)
handleFont(cur, lyx::to_utf8(cmd.argument()), "textrm");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathrm");
break;
case LFUN_FONT_CODE:
if (currentMode() == TEXT_MODE)
handleFont(cur, lyx::to_utf8(cmd.argument()), "texttt");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathtt");
break;
case LFUN_FONT_FRAK:
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathfrak");
break;
case LFUN_FONT_ITAL:
if (currentMode() == TEXT_MODE)
handleFont(cur, lyx::to_utf8(cmd.argument()), "textit");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathit");
break;
case LFUN_FONT_NOUN:
if (currentMode() == TEXT_MODE)
// FIXME: should be "noun"
handleFont(cur, lyx::to_utf8(cmd.argument()), "textsc");
else
handleFont(cur, lyx::to_utf8(cmd.argument()), "mathbb");
break;
//case LFUN_FONT_FREE_APPLY:
handleFont(cur, lyx::to_utf8(cmd.argument()), "textrm");
break;
case LFUN_FONT_DEFAULT:
handleFont(cur, lyx::to_utf8(cmd.argument()), "textnormal");
break;
case LFUN_MATH_MODE: {
#if 1
// ignore math-mode on when already in math mode
if (currentMode() == InsetBase::MATH_MODE && cmd.argument() == "on")
break;
cur.macroModeClose();
string const save_selection = grabAndEraseSelection(cur);
selClearOrDel(cur);
//cur.plainInsert(MathAtom(new InsetMathMBox(cur.bv())));
cur.plainInsert(MathAtom(new InsetMathBox("mbox")));
cur.posLeft();
cur.pushLeft(*cur.nextInset());
cur.niceInsert(save_selection);
#else
if (currentMode() == InsetBase::TEXT_MODE) {
cur.niceInsert(MathAtom(new InsetMathHull("simple")));
cur.message(_("create new math text environment ($...$)"));
} else {
handleFont(cur, lyx::to_utf8(cmd.argument()), "textrm");
cur.message(_("entered math text mode (textrm)"));
}
#endif
break;
}
case LFUN_MATH_SIZE:
#if 0
recordUndo(cur);
cur.setSize(arg);
#endif
break;
case LFUN_MATH_MATRIX: {
recordUndo(cur, Undo::ATOMIC);
unsigned int m = 1;
unsigned int n = 1;
string v_align;
string h_align;
istringstream is(lyx::to_utf8(cmd.argument()));
is >> m >> n >> v_align >> h_align;
if (m < 1)
m = 1;
if (n < 1)
n = 1;
v_align += 'c';
cur.niceInsert(
MathAtom(new InsetMathArray("array", m, n, v_align[0], h_align)));
break;
}
case LFUN_MATH_DELIM: {
string ls;
string rs = lyx::support::split(lyx::to_utf8(cmd.argument()), ls, ' ');
// Reasonable default values
if (ls.empty())
ls = '(';
if (rs.empty())
rs = ')';
recordUndo(cur, Undo::ATOMIC);
cur.handleNest(MathAtom(new InsetMathDelim(ls, rs)));
break;
}
case LFUN_MATH_BIGDELIM: {
string const lname = cmd.getArg(0);
string const ldelim = cmd.getArg(1);
string const rname = cmd.getArg(2);
string const rdelim = cmd.getArg(3);
latexkeys const * l = in_word_set(lname);
bool const have_l = l && l->inset == "big" &&
InsetMathBig::isBigInsetDelim(ldelim);
l = in_word_set(rname);
bool const have_r = l && l->inset == "big" &&
InsetMathBig::isBigInsetDelim(rdelim);
// We mimic LFUN_MATH_DELIM in case we have an empty left
// or right delimiter.
if (have_l || have_r) {
recordUndo(cur, Undo::ATOMIC);
string const selection = grabAndEraseSelection(cur);
selClearOrDel(cur);
if (have_l)
cur.insert(MathAtom(new InsetMathBig(lname,
ldelim)));
cur.niceInsert(selection);
if (have_r)
cur.insert(MathAtom(new InsetMathBig(rname,
rdelim)));
}
// Don't call cur.undispatched() if we did nothing, this would
// lead to infinite recursion via LyXText::dispatch().
break;
}
case LFUN_SPACE_INSERT:
case LFUN_MATH_SPACE:
recordUndo(cur, Undo::ATOMIC);
cur.insert(MathAtom(new InsetMathSpace(",")));
break;
case LFUN_ERT_INSERT:
// interpret this as if a backslash was typed
recordUndo(cur, Undo::ATOMIC);
interpret(cur, '\\');
break;
case LFUN_MATH_SUBSCRIPT:
// interpret this as if a _ was typed
recordUndo(cur, Undo::ATOMIC);
interpret(cur, '_');
break;
case LFUN_MATH_SUPERSCRIPT:
// interpret this as if a ^ was typed
recordUndo(cur, Undo::ATOMIC);
interpret(cur, '^');
break;
// FIXME: We probably should swap parts of "math-insert" and "self-insert"
// handling such that "self-insert" works on "arbitrary stuff" too, and
// math-insert only handles special math things like "matrix".
case LFUN_MATH_INSERT: {
recordUndo(cur, Undo::ATOMIC);
if (cmd.argument() == "^" || cmd.argument() == "_")
interpret(cur, cmd.argument()[0]);
else
cur.niceInsert(lyx::to_utf8(cmd.argument()));
break;
}
case LFUN_DIALOG_SHOW_NEW_INSET: {
string const & name = lyx::to_utf8(cmd.argument());
string data;
if (name == "ref") {
RefInset tmp(name);
data = tmp.createDialogStr(name);
}
cur.bv().showInsetDialog(name, data, 0);
break;
}
case LFUN_INSET_INSERT: {
MathArray ar;
if (createInsetMath_fromDialogStr(lyx::to_utf8(cmd.argument()), ar)) {
recordUndo(cur);
cur.insert(ar);
} else
cur.undispatched();
break;
}
default:
InsetMathDim::doDispatch(cur, cmd);
break;
}
}
bool InsetMathNest::getStatus(LCursor & cur, FuncRequest const & cmd,
FuncStatus & flag) const
{
// the font related toggles
//string tc = "mathnormal";
bool ret = true;
string const arg = lyx::to_utf8(cmd.argument());
switch (cmd.action) {
case LFUN_TABULAR_FEATURE:
flag.enabled(false);
break;
#if 0
case LFUN_TABULAR_FEATURE:
// FIXME: check temporarily disabled
// valign code
char align = mathcursor::valign();
if (align == '\0') {
enable = false;
break;
}
if (cmd.argument().empty()) {
flag.clear();
break;
}
if (!contains("tcb", cmd.argument()[0])) {
enable = false;
break;
}
flag.setOnOff(cmd.argument()[0] == align);
break;
#endif
/// We have to handle them since 1.4 blocks all unhandled actions
case LFUN_FONT_ITAL:
case LFUN_FONT_BOLD:
case LFUN_FONT_SANS:
case LFUN_FONT_EMPH:
case LFUN_FONT_CODE:
case LFUN_FONT_NOUN:
case LFUN_FONT_ROMAN:
case LFUN_FONT_DEFAULT:
flag.enabled(true);
break;
case LFUN_MATH_MUTATE:
//flag.setOnOff(mathcursor::formula()->hullType() == lyx::to_utf8(cmd.argument()));
flag.setOnOff(false);
break;
// we just need to be in math mode to enable that
case LFUN_MATH_SIZE:
case LFUN_MATH_SPACE:
case LFUN_MATH_LIMITS:
case LFUN_MATH_NONUMBER:
case LFUN_MATH_NUMBER:
case LFUN_MATH_EXTERN:
flag.enabled(true);
break;
case LFUN_FONT_FRAK:
flag.enabled(currentMode() != TEXT_MODE);
break;
case LFUN_MATH_INSERT: {
bool const textarg =
arg == "\\textbf" || arg == "\\textsf" ||
arg == "\\textrm" || arg == "\\textmd" ||
arg == "\\textit" || arg == "\\textsc" ||
arg == "\\textsl" || arg == "\\textup" ||
arg == "\\texttt" || arg == "\\textbb" ||
arg == "\\textnormal";
flag.enabled(currentMode() != TEXT_MODE || textarg);
break;
}
case LFUN_MATH_MATRIX:
flag.enabled(currentMode() == MATH_MODE);
break;
case LFUN_INSET_INSERT: {
// Don't test createMathInset_fromDialogStr(), since
// getStatus is not called with a valid reference and the
// dialog would not be applyable.
string const name = cmd.getArg(0);
flag.enabled(name == "ref");
break;
}
case LFUN_MATH_DELIM:
case LFUN_MATH_BIGDELIM:
// Don't do this with multi-cell selections
flag.enabled(cur.selBegin().idx() == cur.selEnd().idx());
break;
default:
ret = false;
break;
}
return ret;
}
void InsetMathNest::edit(LCursor & cur, bool left)
{
cur.push(*this);
cur.idx() = left ? 0 : cur.lastidx();
cur.pos() = left ? 0 : cur.lastpos();
cur.resetAnchor();
//lyxerr << "InsetMathNest::edit, cur:\n" << cur << endl;
}
InsetBase * InsetMathNest::editXY(LCursor & cur, int x, int y)
{
int idx_min = 0;
int dist_min = 1000000;
for (idx_type i = 0, n = nargs(); i != n; ++i) {
int const d = cell(i).dist(x, y);
if (d < dist_min) {
dist_min = d;
idx_min = i;
}
}
MathArray & ar = cell(idx_min);
cur.push(*this);
cur.idx() = idx_min;
cur.pos() = ar.x2pos(x - ar.xo());
//lyxerr << "found cell : " << idx_min << " pos: " << cur.pos() << endl;
if (dist_min == 0) {
// hit inside cell
for (pos_type i = 0, n = ar.size(); i < n; ++i)
if (ar[i]->covers(x, y))
return ar[i].nucleus()->editXY(cur, x, y);
}
return this;
}
void InsetMathNest::lfunMousePress(LCursor & cur, FuncRequest & cmd)
{
//lyxerr << "## lfunMousePress: buttons: " << cmd.button() << endl;
BufferView & bv = cur.bv();
if (cmd.button() == mouse_button::button1) {
//lyxerr << "## lfunMousePress: setting cursor to: " << cur << endl;
bv.mouseSetCursor(cur);
} else if (cmd.button() == mouse_button::button2) {
MathArray ar;
if (cur.selection())
asArray(lyx::to_utf8(bv.cursor().selectionAsString(false)), ar);
else
asArray(lyx::to_utf8(theSelection().get()), ar);
cur.insert(ar);
bv.mouseSetCursor(cur);
}
}
void InsetMathNest::lfunMouseMotion(LCursor & cur, FuncRequest & cmd)
{
// only select with button 1
if (cmd.button() == mouse_button::button1) {
LCursor & bvcur = cur.bv().cursor();
if (bvcur.anchor_.hasPart(cur)) {
//lyxerr << "## lfunMouseMotion: cursor: " << cur << endl;
bvcur.setCursor(cur);
bvcur.selection() = true;
//lyxerr << "MOTION " << bvcur << endl;
}
else {
cur.undispatched();
}
}
}
void InsetMathNest::lfunMouseRelease(LCursor & cur, FuncRequest & cmd)
{
//lyxerr << "## lfunMouseRelease: buttons: " << cmd.button() << endl;
if (cmd.button() == mouse_button::button1) {
//theSelection().put(cur.grabSelection());
return;
}
if (cmd.button() == mouse_button::button3) {
// try to dispatch to enclosed insets first
cur.bv().showDialog("mathpanel");
return;
}
cur.undispatched();
}
bool InsetMathNest::interpret(LCursor & cur, char c)
{
//lyxerr << "interpret 2: '" << c << "'" << endl;
string save_selection;
if (c == '^' || c == '_')
save_selection = grabAndEraseSelection(cur);
cur.clearTargetX();
// handle macroMode
if (cur.inMacroMode()) {
string name = cur.macroName();
/// are we currently typing '#1' or '#2' or...?
if (name == "\\#") {
cur.backspace();
int n = c - '0';
if (n >= 1 && n <= 9)
cur.insert(new MathMacroArgument(n));
return true;
}
if (isalpha(c)) {
cur.activeMacro()->setName(name + c);
return true;
}
// handle 'special char' macros
if (name == "\\") {
// remove the '\\'
if (c == '\\') {
cur.backspace();
if (currentMode() == InsetMath::TEXT_MODE)
cur.niceInsert(createInsetMath("textbackslash"));
else
cur.niceInsert(createInsetMath("backslash"));
} else if (c == '{') {
cur.backspace();
cur.niceInsert(MathAtom(new InsetMathBrace));
} else if (c == '%') {
cur.backspace();
cur.niceInsert(MathAtom(new InsetMathComment));
} else if (c == '#') {
BOOST_ASSERT(cur.activeMacro());
cur.activeMacro()->setName(name + c);
} else {
cur.backspace();
cur.niceInsert(createInsetMath(string(1, c)));
}
return true;
}
// One character big delimiters. The others are handled in
// the other interpret() method.
latexkeys const * l = in_word_set(name.substr(1));
if (name[0] == '\\' && l && l->inset == "big") {
string delim;
switch (c) {
case '{':
delim = "\\{";
break;
case '}':
delim = "\\}";
break;
default:
delim = string(1, c);
break;
}
if (InsetMathBig::isBigInsetDelim(delim)) {
// name + delim ared a valid InsetMathBig.
// We can't use cur.macroModeClose() because
// it does not handle delim.
InsetMathUnknown * p = cur.activeMacro();
p->finalize();
--cur.pos();
cur.cell().erase(cur.pos());
cur.plainInsert(MathAtom(
new InsetMathBig(name.substr(1), delim)));
return true;
}
}
// leave macro mode and try again if necessary
cur.macroModeClose();
if (c == '{')
cur.niceInsert(MathAtom(new InsetMathBrace));
else if (c != ' ')
interpret(cur, c);
return true;
}
// This is annoying as one has to press <space> far too often.
// Disable it.
#if 0
// leave autocorrect mode if necessary
if (autocorrect() && c == ' ') {
autocorrect() = false;
return true;
}
#endif
// just clear selection on pressing the space bar
if (cur.selection() && c == ' ') {
cur.selection() = false;
return true;
}
selClearOrDel(cur);
if (c == '\\') {
//lyxerr << "starting with macro" << endl;
cur.insert(MathAtom(new InsetMathUnknown("\\", false)));
return true;
}
if (c == '\n') {
if (currentMode() == InsetMath::TEXT_MODE)
cur.insert(c);
return true;
}
if (c == ' ') {
if (currentMode() == InsetMath::TEXT_MODE) {
// insert spaces in text mode,
// but suppress direct insertion of two spaces in a row
// the still allows typing '<space>a<space>' and deleting the 'a', but
// it is better than nothing...
if (!cur.pos() != 0 || cur.prevAtom()->getChar() != ' ')
cur.insert(c);
return true;
}
if (cur.pos() != 0 && cur.prevAtom()->asSpaceInset()) {
cur.prevAtom().nucleus()->asSpaceInset()->incSpace();
return true;
}
if (cur.popRight())
return true;
// if are at the very end, leave the formula
return cur.pos() != cur.lastpos();
}
// These shouldn't work in text mode:
if (currentMode() != InsetMath::TEXT_MODE) {
if (c == '_') {
script(cur, false, save_selection);
return true;
}
if (c == '^') {
script(cur, true, save_selection);
return true;
}
if (c == '~') {
cur.niceInsert(createInsetMath("sim"));
return true;
}
}
if (c == '{' || c == '}' || c == '&' || c == '$' || c == '#' ||
c == '%' || c == '_' || c == '^') {
cur.niceInsert(createInsetMath(string(1, c)));
return true;
}
// try auto-correction
//if (autocorrect() && hasPrevAtom() && math_autocorrect(prevAtom(), c))
// return true;
// no special circumstances, so insert the character without any fuss
cur.insert(c);
cur.autocorrect() = true;
return true;
}
bool InsetMathNest::interpret(LCursor & cur, string const & str)
{
// Create a InsetMathBig from cur.cell()[cur.pos() - 1] and t if
// possible
if (!cur.empty() && cur.pos() > 0 &&
cur.cell()[cur.pos() - 1]->asUnknownInset()) {
if (InsetMathBig::isBigInsetDelim(str)) {
string prev = asString(cur.cell()[cur.pos() - 1]);
if (prev[0] == '\\') {
prev = prev.substr(1);
latexkeys const * l = in_word_set(prev);
if (l && l->inset == "big") {
cur.cell()[cur.pos() - 1] =
MathAtom(new InsetMathBig(prev, str));
return true;
}
}
}
}
return false;
}
bool InsetMathNest::script(LCursor & cur, bool up, string const &
save_selection)
{
// Hack to get \^ and \_ working
//lyxerr << "handling script: up: " << up << endl;
if (cur.inMacroMode() && cur.macroName() == "\\") {
if (up)
cur.niceInsert(createInsetMath("mathcircumflex"));
else
interpret(cur, '_');
return true;
}
cur.macroModeClose();
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
if (asScriptInset() && cur.idx() == 0) {
// we are in a nucleus of a script inset, move to _our_ script
InsetMathScript * inset = asScriptInset();
//lyxerr << " going to cell " << inset->idxOfScript(up) << endl;
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
inset->ensure(up);
cur.idx() = inset->idxOfScript(up);
cur.pos() = 0;
} else if (cur.pos() != 0 && cur.prevAtom()->asScriptInset()) {
--cur.pos();
InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
cur.push(*inset);
inset->ensure(up);
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
cur.idx() = inset->idxOfScript(up);
cur.pos() = cur.lastpos();
} else {
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
// convert the thing to our left to a scriptinset or create a new
// one if in the very first position of the array
if (cur.pos() == 0) {
//lyxerr << "new scriptinset" << endl;
cur.insert(new InsetMathScript(up));
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
} else {
//lyxerr << "converting prev atom " << endl;
cur.prevAtom() = MathAtom(new InsetMathScript(cur.prevAtom(), up));
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
}
--cur.pos();
InsetMathScript * inset = cur.nextAtom().nucleus()->asScriptInset();
// special handling of {}-bases
// is this always correct?
if (inset->nuc().size() == 1
&& inset->nuc().back()->asBraceInset())
inset->nuc() = inset->nuc().back()->asNestInset()->cell(0);
the stuff from the sneak preview: For one, it still contains a few things that are already in CVS (the 'brown paperbag' changes). Secondly, this changes the ParagraphList to a std::vector but does not yet take full advantage of it except removing LyXText::parOffset() and similar. I had an extensive talk with my profiler and we are happy nevertheless. This also moves almost all Cut&Paste specific stuff from text.C to CutAndPaste.C. Much smaller interface now... Namespace CutAndPaste is now lyx::cap::. Was inconsistent with the rest.... Make ParagraphList a proper class. We'll need this later for a specialized erase/insert. Remove some unneeded prototypes and function declarations Use ParameterStruct directly instead of ShareContainer<ParameterStruct> Inline a few accesses to CursorSlice members as suggested by the profiler. Fix commandline conversion crash reported by Kayvan. Replace PosIterator by DocumentIterator. The latter can also iterate through math and nested text in math... Remove math specific hack from Documentiterator Derive InsetCollapsable from InsetText instead of using an InsetText member. This give us the opportunity to get rid of the InsetOld::owner_ backpointer. Cosmetics in CutAndPaste.C and cursor.C. Fix nasty crash (popping slices off an empty selection anchor). Add a few asserts. Remove all 'manual' update calls. We do now one per user interaction which is completely sufficient. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8527 a592a061-630c-0410-9148-cb99ea01b6c8
2004-03-25 09:16:36 +00:00
cur.push(*inset);
cur.idx() = 1;
cur.pos() = 0;
}
//lyxerr << "inserting selection 1:\n" << save_selection << endl;
cur.niceInsert(save_selection);
cur.resetAnchor();
//lyxerr << "inserting selection 2:\n" << save_selection << endl;
return true;
}