#include <sys/types.h>
#include "curses_inc.h"
#define _ISMARK2(x) (mks[(x) / BITSPERBYTE] & (1<<((x) % BITSPERBYTE)))
#define H_UP -1
#define H_DO 1
static int Newy;
static int _homefirst(int, int, int, int),
_mvrel(int, int, int, int, int),
_mvvert(int, int, int), _mvhor(int, int, int),
_mvright(int, int, int), _mvleft(int, int, int);
int
mvcur(int cury, int curx, int newy, int newx)
{
int hu,
hd,
rl,
cm;
if (cury == newy && curx == newx)
return (OK);
if (SP->fl_endwin)
return (ERR);
if (!move_standout_mode && curscr->_attrs && !SP->_mks)
_VIDS(A_NORMAL, curscr->_attrs);
if (!move_insert_mode && SP->phys_irm)
_OFFINSERT();
Newy = newy;
cm = _COST(Cursor_address);
rl = hd = hu = LARGECOST;
if (cm < LARGECOST && SP->baud >= 2400 &&
cury >= 0 && cury < curscr->_maxy &&
curx >= 0 && curx < curscr->_maxx) {
if (cursor_down && (newy == (cury + 1)) &&
((newx == curx) || (newx == 0 && carriage_return))) {
if (newx != curx)
_PUTS(carriage_return, 1);
_PUTS(cursor_down, 1);
goto done;
}
if (cury == newy && newx < curx - 4 && newx > curx + 4) {
if (newx < curx)
rl = _mvleft(curx, newx, FALSE);
else
rl = _mvright(curx, newx, FALSE);
if (rl < cm) {
if (newx < curx)
rl = _mvleft(curx, newx, TRUE);
else
rl = _mvright(curx, newx, TRUE);
goto done;
}
}
}
if (rl >= LARGECOST && cury >= 0 && cury < curscr->_maxy &&
curx >= 0 && curx < curscr->_maxx)
rl = _mvrel(cury, curx, newy, newx, FALSE);
if (cursor_home)
hu = _homefirst(newy, newx, H_UP, FALSE);
if (cursor_to_ll)
hd = _homefirst(newy, newx, H_DO, FALSE);
if (cm >= LARGECOST && rl >= LARGECOST && hu >= LARGECOST &&
hd >= LARGECOST)
return (ERR);
if (cm <= rl && cm <= hu && cm <= hd)
_PUTS(tparm_p2(cursor_address, newy, newx), 1);
else
if (rl <= hu && rl <= hd)
(void) _mvrel(cury, curx, newy, newx, TRUE);
else
(void) _homefirst(newy, newx, hu <= hd ?
H_UP : H_DO, TRUE);
done:
curscr->_curx = (short) newx;
curscr->_cury = (short) newy;
return (OK);
}
static int
_homefirst(int ny, int nx, int type, int doit)
{
char *home;
int cy, cost;
if (type == H_UP) {
home = cursor_home;
cost = _COST(Cursor_home);
cy = 0;
} else {
home = cursor_to_ll;
cost = _COST(Cursor_to_ll);
cy = curscr->_maxy - 1;
}
if (!home)
return (LARGECOST);
if (!doit)
return (cost + _mvrel(cy, 0, ny, nx, FALSE));
_PUTS(home, 1);
return (_mvrel(cy, 0, ny, nx, TRUE));
}
static int
_mvrel(int cy, int cx, int ny, int nx, int doit)
{
int cv, ch;
cv = _mvvert(cy, ny, doit);
ch = _mvhor(cx, nx, doit);
return (cv + ch);
}
static int
_mvvert(int cy, int ny, int doit)
{
char *ve;
int dy, st_1, st_n, cv;
if (cy == ny)
goto out;
if (cy < ny) {
dy = ny-cy;
st_1 = _COST(Cursor_down) * dy;
st_n = _COST(Parm_down_cursor);
} else {
dy = cy-ny;
st_1 = _COST(Cursor_up) * dy;
st_n = _COST(Parm_up_cursor);
}
cv = _COST(Row_address);
if (!doit)
return ((cv < st_1 && cv < st_n) ? cv :
(st_n < st_1) ? st_n : st_1);
if (cv < st_1 && cv < st_n)
_PUTS(tparm_p1(row_address, ny), 1);
else
if (st_n < st_1) {
if (cy < ny)
_PUTS(tparm_p1(parm_down_cursor, dy), 1);
else
_PUTS(tparm_p1(parm_up_cursor, dy), 1);
} else {
if (cy < ny)
ve = cursor_down;
else
ve = cursor_up;
for (; dy > 0; --dy)
_PUTS(ve, 1);
}
out:
return (0);
}
static int
_mvhor(int cx, int nx, int doit)
{
int st, ch, hl;
if (cx == nx)
goto out;
ch = _COST(Row_address);
st = cx < nx ? _mvright(cx, nx, FALSE) : _mvleft(cx, nx, FALSE);
hl = (_COST(Carriage_return) < LARGECOST) ?
_COST(Carriage_return) + _mvright(0, nx, FALSE) : LARGECOST;
if (!doit)
return ((ch < st && ch < hl) ? ch : (hl < st ? hl : st));
if (ch < st && ch < hl)
_PUTS(tparm_p1(column_address, nx), 1);
else
if (hl < st) {
_PUTS(carriage_return, 1);
(void) _mvright(0, nx, TRUE);
} else {
if (cx < nx)
(void) _mvright(cx, nx, TRUE);
else
(void) _mvleft(cx, nx, TRUE);
}
out:
return (0);
}
static int
_mvright(int cx, int nx, int doit)
{
chtype *scp;
char *mks;
int nt, tx, x, stcost, iscont;
if (!cursor_right && !parm_right_cursor)
return (LARGECOST);
scp = curscr->_y[Newy];
mks = magic_cookie_glitch >= 0 ? SP->_mks[Newy] : NULL;
if (cursor_right) {
nt = tab ? (nx / TABSIZE - cx / TABSIZE) : 0;
tx = (nt > 0) ? (cx / TABSIZE + nt) * TABSIZE : cx;
stcost = nt * _COST(Tab);
iscont = 0;
for (x = tx; x < nx; ++x) {
if (iscont == 0 && !ISCBIT(scp[x]))
iscont = 1;
if ((!ceol_standout_glitch && !mks &&
_ATTR(scp[x]) == curscr->_attrs) ||
ceol_standout_glitch || (mks && !_ISMARK2(x))) {
if (!ISMBIT(scp[x]))
stcost += 1;
else if (iscont && !(nx - x == 1 && nx <
curscr->_maxx && ISCBIT(scp[nx])))
stcost += 1;
else
stcost += _COST(Cursor_right);
} else
stcost += _COST(Cursor_right);
}
} else
stcost = LARGECOST;
if (!doit)
return ((_COST(Parm_right_cursor) < stcost) ?
_COST(Parm_right_cursor) : stcost);
if (_COST(Parm_right_cursor) < stcost)
_PUTS(tparm_p1(parm_right_cursor, nx-cx), 1);
else {
if (SP->phys_irm)
_OFFINSERT();
for (; nt > 0; --nt)
_PUTS(tab, 1);
iscont = 0;
for (x = tx; x < nx; ++x) {
if (iscont == 0 && !ISCBIT(scp[x]))
iscont = 1;
if ((!ceol_standout_glitch && !mks &&
_ATTR(scp[x]) == curscr->_attrs) ||
ceol_standout_glitch || (mks && !_ISMARK2(x))) {
if (!ISMBIT(scp[x]))
(void) _outwch(_CHAR(scp[x]));
else if (iscont && !(nx - x == 1 &&
nx < curscr->_maxx && ISCBIT(scp[nx])))
(void) _outwch(_CHAR(scp[x]));
else
_PUTS(cursor_right, 1);
} else
_PUTS(cursor_right, 1);
}
}
return (0);
}
static int
_mvleft(int cx, int nx, int doit)
{
int tx, nt, x, stcost;
if (!cursor_left && !parm_left_cursor)
return (LARGECOST);
if (cursor_left) {
tx = cx;
nt = 0;
if (back_tab) {
x = (nx % TABSIZE) ? (nx / TABSIZE + 1) * TABSIZE : nx;
if (x < cx) {
nt = (cx / TABSIZE - x / TABSIZE) +
((cx % TABSIZE) ? 1 : 0);
tx = x;
}
}
stcost = nt * _COST(Back_tab) + (tx-nx) * _COST(Cursor_left);
} else
stcost = LARGECOST;
if (!doit)
return ((_COST(Parm_left_cursor) < stcost) ?
_COST(Parm_left_cursor) : stcost);
if (_COST(Parm_left_cursor) < stcost)
_PUTS(tparm_p1(parm_left_cursor, cx - nx), 1);
else {
for (; nt > 0; --nt)
_PUTS(back_tab, 1);
for (; tx > nx; --tx)
_PUTS(cursor_left, 1);
}
return (0);
}