lyx_mirror/src/cursor.C
André Pönitz 09c7f0bf77 remove typo
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8336 a592a061-630c-0410-9148-cb99ea01b6c8
2004-01-13 11:41:35 +00:00

220 lines
4.8 KiB
C

/**
* \file cursor.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author André Pönitz
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "buffer.h"
#include "BufferView.h"
#include "cursor.h"
#include "debug.h"
#include "dispatchresult.h"
#include "funcrequest.h"
#include "iterators.h"
#include "lfuns.h"
#include "lyxtext.h"
#include "paragraph.h"
#include "lyxrow.h"
#include "insets/updatableinset.h"
#include "insets/insettabular.h"
#include "insets/insettext.h"
#include <boost/assert.hpp>
using std::vector;
using std::endl;
std::ostream & operator<<(std::ostream & os, LCursor const & cursor)
{
os << "\n";
for (size_t i = 0, n = cursor.data_.size(); i != n; ++i)
os << " " << cursor.data_[i] << "\n";
return os;
}
LCursor::LCursor(BufferView * bv)
: data_(1), bv_(bv)
{}
DispatchResult LCursor::dispatch(FuncRequest const & cmd0)
{
lyxerr << "\nLCursor::dispatch: " << *this << endl;
FuncRequest cmd = cmd0;
for (int i = data_.size() - 1; i >= 1; --i) {
CursorSlice const & citem = data_[i];
lyxerr << "trying to dispatch to inset " << citem.inset_ << endl;
DispatchResult res = citem.inset_->dispatch(cmd);
if (res.dispatched()) {
lyxerr << " successfully dispatched to inset " << citem.inset_ << endl;
return DispatchResult(true, true);
}
// remove one level of cursor
switch (res.val()) {
case FINISHED:
pop(i);
cmd = FuncRequest(bv_, LFUN_FINISHED_LEFT);
break;
case FINISHED_RIGHT:
pop(i);
cmd = FuncRequest(bv_, LFUN_FINISHED_RIGHT);
break;
case FINISHED_UP:
pop(i);
cmd = FuncRequest(bv_, LFUN_FINISHED_UP);
break;
case FINISHED_DOWN:
pop(i);
cmd = FuncRequest(bv_, LFUN_FINISHED_DOWN);
break;
default:
lyxerr << "not handled on level " << i << " val: " << res.val() << endl;
break;
}
}
lyxerr << "trying to dispatch to main text " << bv_->text() << endl;
DispatchResult res = bv_->text()->dispatch(cmd);
lyxerr << " result: " << res.val() << endl;
if (!res.dispatched()) {
lyxerr << "trying to dispatch to bv " << bv_ << endl;
bool sucess = bv_->dispatch(cmd);
lyxerr << " result: " << sucess << endl;
res.dispatched(sucess);
}
return res;
}
void LCursor::push(UpdatableInset * inset)
{
lyxerr << "LCursor::push() inset: " << inset << endl;
data_.push_back(CursorSlice(inset));
updatePos();
}
void LCursor::pop(int depth)
{
lyxerr << "LCursor::pop() to " << depth << endl;
while (data_.size() > 1 && depth < data_.size()) {
lyxerr << "LCursor::pop a level " << endl;
data_.pop_back();
}
}
void LCursor::pop()
{
lyxerr << "LCursor::pop() " << endl;
//BOOST_ASSERT(!data_.empty());
if (data_.size() <= 1)
lyxerr << "### TRYING TO POP FROM EMPTY CURSOR" << endl;
else
data_.pop_back();
}
UpdatableInset * LCursor::innerInset() const
{
return data_.size() <= 1 ? 0 : data_.back().asUpdatableInset();
}
LyXText * LCursor::innerText() const
{
if (data_.size() > 1) {
// go up until first non-0 text is hit
// (innermost text is 0 e.g. for mathed and the outer tabular level)
for (int i = data_.size() - 1; i >= 1; --i)
if (data_[i].text())
return data_[i].text();
}
return bv_->text();
}
void LCursor::updatePos()
{
if (data_.size() > 1)
cached_y_ = bv_->top_y() + innerInset()->y();
}
void LCursor::getDim(int & asc, int & desc) const
{
LyXText * txt = innerText();
if (txt) {
Row const & row = *txt->cursorRow();
asc = row.baseline();
desc = row.height() - asc;
} else
innerInset()->getCursorDim(asc, desc);
}
void LCursor::getPos(int & x, int & y) const
{
if (data_.size() <= 1) {
x = bv_->text()->cursorX();
y = bv_->text()->cursorY();
// y -= bv_->top_y();
} else {
// Would be nice to clean this up to make some understandable sense...
UpdatableInset * inset = innerInset();
// Non-obvious. The reason we have to have these
// extra checks is that the ->getCursor() calls rely
// on the inset's own knowledge of its screen position.
// If we scroll up or down in a big enough increment, the
// inset->draw() is not called: this doesn't update
// inset.top_baseline, so getCursor() returns an old value.
// Ugly as you like.
inset->getCursorPos(data_.back().idx_, x, y);
x += inset->x();
y += cached_y_;
}
}
UpdatableInset * LCursor::innerInsetOfType(int code) const
{
for (int i = data_.size() - 1; i >= 1; --i)
if (data_[i].asUpdatableInset()->lyxCode() == code)
return data_[i].asUpdatableInset();
return 0;
}
InsetTabular * LCursor::innerInsetTabular() const
{
return static_cast<InsetTabular *>
(innerInsetOfType(InsetOld::TABULAR_CODE));
}
void LCursor::cell(int idx)
{
BOOST_ASSERT(!data_.empty());
data_.back().idx_ = idx;
}
int LCursor::cell() const
{
BOOST_ASSERT(!data_.empty());
return data_.back().idx_;
}