#include "intl.h"
#include "support/lstrings.h"
#include "frontends/LyXView.h"
+#include "frontends/screen.h"
#include "frontends/WorkArea.h"
#include "insets/insetspecialchar.h"
#include "insets/insettext.h"
+#include "undo_funcs.h"
+using std::endl;
extern string current_layout;
+namespace {
+
+void cursorPrevious(LyXText * text, BufferView * bv)
+{
+ if (!text->cursor.row()->previous()) {
+ if (text->first_y > 0) {
+ int new_y = bv->text->first_y - bv->workarea().workHeight();
+ bv->screen().draw(bv->text, bv, new_y < 0 ? 0 : new_y);
+ bv->updateScrollbar();
+ }
+ return;
+ }
+
+ int y = text->first_y;
+ Row * cursorrow = text->cursor.row();
+
+ text->setCursorFromCoordinates(bv, text->cursor.x_fix(), y);
+ finishUndo();
+
+ int new_y;
+ if (cursorrow == bv->text->cursor.row()) {
+ // we have a row which is higher than the workarea so we leave the
+ // cursor on the start of the row and move only the draw up as soon
+ // as we move the cursor or do something while inside the row (it may
+ // span several workarea-heights) we'll move to the top again, but this
+ // is better than just jump down and only display part of the row.
+ new_y = bv->text->first_y - bv->workarea().workHeight();
+ } else {
+ if (text->inset_owner) {
+ new_y = bv->text->cursor.iy()
+ + bv->theLockingInset()->insetInInsetY() + y
+ + text->cursor.row()->height()
+ - bv->workarea().workHeight() + 1;
+ } else {
+ new_y = text->cursor.y()
+ - text->cursor.row()->baseline()
+ + text->cursor.row()->height()
+ - bv->workarea().workHeight() + 1;
+ }
+ }
+ bv->screen().draw(bv->text, bv, new_y < 0 ? 0 : new_y);
+ if (text->cursor.row()->previous()) {
+ LyXCursor cur;
+ text->setCursor(bv, cur, text->cursor.row()->previous()->par(),
+ text->cursor.row()->previous()->pos(), false);
+ if (cur.y() > text->first_y) {
+ text->cursorUp(bv, true);
+ }
+ }
+ bv->updateScrollbar();
+}
+
+
+void cursorNext(LyXText * text, BufferView * bv)
+{
+ if (!text->cursor.row()->next()) {
+ int y = text->cursor.y() - text->cursor.row()->baseline() +
+ text->cursor.row()->height();
+ if (y > int(text->first_y + bv->workarea().workHeight())) {
+ bv->screen().draw(bv->text, bv,
+ bv->text->first_y + bv->workarea().workHeight());
+ bv->updateScrollbar();
+ }
+ return;
+ }
+
+ int y = text->first_y + bv->workarea().workHeight();
+ if (text->inset_owner && !text->first_y) {
+ y -= (bv->text->cursor.iy()
+ - bv->text->first_y
+ + bv->theLockingInset()->insetInInsetY());
+ }
+
+ text->getRowNearY(y);
+
+ Row * cursorrow = text->cursor.row();
+ text->setCursorFromCoordinates(bv, text->cursor.x_fix(), y);
+ // + workarea().workHeight());
+ finishUndo();
+
+ int new_y;
+ if (cursorrow == bv->text->cursor.row()) {
+ // we have a row which is higher than the workarea so we leave the
+ // cursor on the start of the row and move only the draw down as soon
+ // as we move the cursor or do something while inside the row (it may
+ // span several workarea-heights) we'll move to the top again, but this
+ // is better than just jump down and only display part of the row.
+ new_y = bv->text->first_y + bv->workarea().workHeight();
+ } else {
+ if (text->inset_owner) {
+ new_y = bv->text->cursor.iy()
+ + bv->theLockingInset()->insetInInsetY()
+ + y - text->cursor.row()->baseline();
+ } else {
+ new_y = text->cursor.y() - text->cursor.row()->baseline();
+ }
+ }
+ bv->screen().draw(bv->text, bv, new_y);
+ if (text->cursor.row()->next()) {
+ LyXCursor cur;
+ text->setCursor(bv, cur, text->cursor.row()->next()->par(),
+ text->cursor.row()->next()->pos(), false);
+ if (cur.y() < int(text->first_y + bv->workarea().workHeight())) {
+ text->cursorDown(bv, true);
+ }
+ }
+ bv->updateScrollbar();
+}
+
+}
+
+
void LyXText::update(BufferView * bv, bool changed)
{
BufferView::UpdateCodes c = BufferView::SELECT | BufferView::FITCUR;
Inset::RESULT LyXText::dispatch(FuncRequest const & cmd)
{
+ lyxerr[Debug::ACTION] << "LyXFunc::dispatch: action[" << cmd.action
+ <<"] arg[" << cmd.argument << "]" << endl;
+
BufferView * bv = cmd.view();
switch (cmd.action) {
bv->finishChange();
break;
- case LFUN_WORDRIGHT:
+ case LFUN_WORDRIGHT:
if (!selection.mark())
bv->beforeChange(this);
update(bv, false);
case LFUN_PRIORSEL:
update(bv, false);
- bv->cursorPrevious(this);
+ cursorPrevious(this, bv);
bv->finishChange(true);
break;
case LFUN_NEXTSEL:
update(bv, false);
- bv->cursorNext(this);
+ cursorNext(this, bv);
bv->finishChange();
break;
if (!selection.mark())
bv->beforeChange(this);
bv->update(this, BufferView::UPDATE);
- bv->cursorPrevious(this);
+ cursorPrevious(this, bv);
bv->finishChange(false);
// was:
// finishUndo();
if (!selection.mark())
bv->beforeChange(this);
bv->update(this, BufferView::UPDATE);
- bv->cursorNext(this);
+ cursorNext(this, bv);
bv->finishChange(false);
break;
case LFUN_SETXY: {
int x = 0;
int y = 0;
- if (::sscanf(cmd.argument.c_str(), " %d %d", &x, &y) != 2)
+ istringstream is(cmd.argument.c_str());
+ is >> x >> y;
+ if (!is)
lyxerr << "SETXY: Could not parse coordinates in '"
<< cmd.argument << std::endl;
- setCursorFromCoordinates(bv, x, y);
+ else
+ setCursorFromCoordinates(bv, x, y);
break;
}
if (!clip.empty()) {
if (cmd.argument == "paragraph")
insertStringAsParagraphs(bv, clip);
- else
+ else
insertStringAsLines(bv, clip);
clearSelection();
update(bv);