Ejemplo n.º 1
0
int
wclrtoeol(WINDOW *win)
{
	char	*sp, *end;
	int	y, x;
	char	*maxx;
	ptrdiff_t	minx;

	y = win->_cury;
	x = win->_curx;
	end = &win->_y[y][win->_maxx];
	minx = _NOCHANGE;
	maxx = &win->_y[y][x];
	for (sp = maxx; sp < end; sp++)
		if (*sp != ' ') {
			maxx = sp;
			if (minx == _NOCHANGE)
				minx = sp - win->_y[y];
			*sp = ' ';
		}
	/*
	 * update firstch and lastch for the line
	 */
	(void) touchline(win, y, win->_curx, win->_maxx - 1);

#ifdef DEBUG
	fprintf(outf, "CLRTOEOL: minx = %d, maxx = %d, firstch = %d,"
	    " lastch = %d\n", minx, maxx - win->_y[y], win->_firstch[y],
	    win->_lastch[y]);
#endif
	return (OK);
}
Ejemplo n.º 2
0
int
touchoverlap(WINDOW *win1, WINDOW *win2)
{
	int	y, endy, endx, starty, startx;

#ifdef DEBUG
	fprintf(outf, "TOUCHOVERLAP(%0.2o, %0.2o);\n", win1, win2);
#endif
	starty = max(win1->_begy, win2->_begy);
	startx = max(win1->_begx, win2->_begx);
	endy = min(win1->_maxy + win1->_begy, win2->_maxy + win2->_begy);
	endx = min(win1->_maxx + win1->_begx, win2->_maxx + win2->_begx);
#ifdef DEBUG
	fprintf(outf, "TOUCHOVERLAP:from (%d,%d) to (%d,%d)\n",
	    starty, startx, endy, endx);
	fprintf(outf, "TOUCHOVERLAP:win1 (%d,%d) to (%d,%d)\n",
	    win1->_begy, win1->_begx, win1->_begy + win1->_maxy,
	    win1->_begx + win1->_maxx);
	fprintf(outf, "TOUCHOVERLAP:win2 (%d,%d) to (%d,%d)\n",
	    win2->_begy, win2->_begx, win2->_begy + win2->_maxy,
	    win2->_begx + win2->_maxx);
#endif
	if (starty >= endy || startx >= endx)
		return (OK);
	starty -= win2->_begy;
	startx -= win2->_begx;
	endy -= win2->_begy;
	endx -= win2->_begx;
	endx--;
	for (y = starty; y < endy; y++)
		(void) touchline(win2, y, startx, endx);
	return (OK);
}
Ejemplo n.º 3
0
/*
 *  std_touch_top
 *  Touch the line in all windows which is visible above a given line.
 *  This routine is almost identical to touch_top, except that the "panel"
 *  is stdscr in this case.  The "obscured" list is the list of panels.
 */
static void
std_touch_top(int line, PANEL *obs_pnl, int start_x, int end_x)
{
	PANEL	*next_obs;

	do {
		next_obs = obs_pnl -> below;

		if (line >= obs_pnl->wstarty && line <= obs_pnl->wendy &&
		    obs_pnl->wstartx <= end_x && obs_pnl->wendx >= start_x) {
			(void) touchline(obs_pnl->win,
			    line - obs_pnl->wstarty, 1);
			if (obs_pnl->wstartx > start_x &&
			    obs_pnl->wendx < end_x) {
				if (next_obs)
					std_touch_top(line, next_obs,
					    obs_pnl->wendx+1, end_x);
				end_x = obs_pnl -> wstartx - 1;
			} else {
				if (obs_pnl->wstartx <= start_x)
					start_x = obs_pnl -> wendx + 1;
				if (obs_pnl->wendx >= end_x)
					end_x = obs_pnl -> wstartx - 1;
				if (start_x > end_x)
					return;
			}
		}
	}
	while ((obs_pnl = next_obs) != 0);
}
Ejemplo n.º 4
0
static void
update_status(WINDOW *win, STATUS * sp)
{
    switch (sp->ch) {
    case ' ':			/* next test-iteration */
	if (has_colors()) {
	    if ((sp->c_msg = color_params(++(sp->c), &(sp->pair))) == 0) {
		sp->c_msg = color_params(sp->c = 0, &(sp->pair));
		if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
		    sp->v_msg = video_params(sp->v = 0, &(sp->attr));
		}
	    }
	} else {
	    if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) {
		sp->v_msg = video_params(sp->v = 0, &(sp->attr));
	    }
	}
	sp->count = 0;
	show_status(win, sp);
	break;
    case KEY_LEFT:
    case 'h':
	if (sp->x_val > 0)
	    wmove(win, sp->y_val, --(sp->x_val));
	break;
    case KEY_DOWN:
    case 'j':
	if (sp->y_val < sp->y_max)
	    wmove(win, ++(sp->y_val), sp->x_val);
	break;
    case KEY_UP:
    case 'k':
	if (sp->y_val > 0)
	    wmove(win, --(sp->y_val), sp->x_val);
	break;
    case KEY_RIGHT:
    case 'l':
	if (sp->x_val < sp->x_max)
	    wmove(win, sp->y_val, ++(sp->x_val));
	break;
    case 't':
	touchline(win, sp->y_val, 1);
	break;
    case '=':
	sp->count = 0;
	show_status(win, sp);
	break;
    case '?':
	do_subwindow(win, sp, show_help);
	break;
    default:
	if (isdigit(sp->ch)) {
	    sp->count = (sp->count * 10) + (sp->ch - '0');
	    show_status(win, sp);
	} else {
	    beep();
	}
	break;
    }
}
Ejemplo n.º 5
0
void 
ScrollText(void)
{
#ifdef UNIX
    register int i;

    /*
     * Ugh, is this dirty.
     * A better approach would be to use subwin() and
     * scroll the subwindow, but this doesn't work
     * very well in some versions of ncurses.
     */
//    for (i = 5; i < ScrnHeight - 2; i++)
    /* This is actually ncurses/curses dependant */
//#if defined(linux) || defined(_linux)
//	memcpy(stdscr->_line[i].text, stdscr->_line[i+1].text,
//#else
//	memcpy(stdscr->_line[i], stdscr->_line[i + 1],
//#endif
//		42 * sizeof(chtype));
    touchline(stdscr, 5, ScrnHeight - 2);
    SetColor();
    FillBox(1, ScrnHeight - 2, 42, 1, ' ');
    refresh();
#else
    CopyText(2, 8, 42, ScrnHeight - 9, 2, 7);
    FillBox(1, ScrnHeight - 2, 42, 1, ' ');
#endif
}
Ejemplo n.º 6
0
/*
 * touch_top - Touch the line in all windows
 * which is visible above a given line
 */
static void
touch_top(PANEL *panel, int line, _obscured_list *obs, int start_x, int end_x)
{
	PANEL		*pnl;
	_obscured_list	*next_obs;

	do {
		pnl = obs -> panel_p;
		if ((next_obs = obs->next) == panel -> obscured -> next)
			next_obs = 0;

		if (line >= obs -> start && line <= obs -> end &&
		    pnl->wstartx <= end_x && pnl->wendx >= start_x) {
			(void) touchline(pnl->win, line - pnl->wstarty, 1);
			if (pnl->wstartx > start_x && pnl->wendx < end_x) {
				if (next_obs)
					touch_top(panel, line, next_obs,
					    pnl->wendx+1, end_x);
				end_x = pnl -> wstartx - 1;
			} else {
				if (pnl->wstartx <= start_x)
					start_x = pnl -> wendx + 1;
				if (pnl->wendx >= end_x)
					end_x = pnl -> wstartx - 1;
				if (start_x > end_x)
					return;
			}
		}
	}
	while ((obs = next_obs) != 0);
}
Ejemplo n.º 7
0
static void Touchline(PANEL *pan, int start, int count)
{
    char s80[80];

    sprintf(s80, "Touchline s=%d c=%d", start, count);
    dPanel(s80, pan);
    touchline(pan->win, start, count);
}
Ejemplo n.º 8
0
wredrawln(WINDOW *win, int beg, int num)
{
    int i;
    int end;
    size_t len;

    T((T_CALLED("wredrawln(%p,%d,%d)"), win, beg, num));

    if (win == 0)
	returnCode(ERR);

    if (beg < 0)
	beg = 0;

    if (touchline(win, beg, num) == ERR)
	returnCode(ERR);

    if (touchline(curscr, beg + win->_begy, num) == ERR)
	returnCode(ERR);

    end = beg + num;
    if (end > curscr->_maxy + 1)
	end = curscr->_maxy + 1;
    if (end > win->_maxy + 1)
	end = win->_maxy + 1;

    len = (win->_maxx + 1);
    if (len > (size_t) (curscr->_maxx + 1))
	len = (size_t) (curscr->_maxx + 1);
    len *= sizeof(curscr->_line[0].text[0]);

    for (i = beg; i < end; i++) {
	int crow = i + win->_begy;

	memset(curscr->_line[crow].text + win->_begx, 0, len);
	_nc_make_oldhash(crow);
    }

    returnCode(OK);
}
Ejemplo n.º 9
0
/*
 *	This routine performs an insert-char on the line, leaving
 * (_cury,_curx) unchanged.
 *
 */
int wdelch(reg WINDOW	*win )
{
	reg char	*temp1, *temp2;
	reg char	*end;

	end = &win->_y[win->_cury][win->_maxx - 1];
	temp1 = &win->_y[win->_cury][win->_curx];
	temp2 = temp1 + 1;
	while (temp1 < end)
		*temp1++ = *temp2++;
	*temp1 = ' ';
	touchline(win, win->_cury, win->_curx, win->_maxx - 1);
	return OK;
}
Ejemplo n.º 10
0
int wscrl(WINDOW *win, int n)
{
    int i, l, dir, start, end;
    chtype blank, *temp;

    /* Check if window scrolls. Valid for window AND pad */

    if (!win || !win->_scroll || !n)
        return ERR;

    blank = win->_bkgd;

    if (n > 0)
    {
        start = win->_tmarg;
        end = win->_bmarg;
        dir = 1;
    }
    else
    {
        start = win->_bmarg;
        end = win->_tmarg;
        dir = -1;
    }

    for (l = 0; l < (n * dir); l++) 
    {
        temp = win->_y[start];

        /* re-arrange line pointers */

        for (i = start; i != end; i += dir)
            win->_y[i] = win->_y[i + dir];

        win->_y[end] = temp;

        /* make a blank line */

        for (i = 0; i < win->_maxx; i++)
            *temp++ = blank;
    }

    touchline(win, win->_tmarg, win->_bmarg - win->_tmarg + 1);

    PDC_sync(win);
    return OK;
}
Ejemplo n.º 11
0
/*
 *	This routine erases everything on the window.
 *
 */
void wclrtobot(reg WINDOW * win )
  {
	reg int		y;
	reg char	*sp, *end, *maxx;
	reg int		startx, minx;

	startx = win->_curx;
	for (y = win->_cury; y < win->_maxy; y++) {
		minx = _NOCHANGE;
		end = &win->_y[y][win->_maxx];
		for (maxx = sp = &win->_y[y][startx]; sp < end; sp++)
			if (*sp != ' ') {
				maxx = sp;
				if (minx == _NOCHANGE)
					minx = sp - win->_y[y];
				*sp = ' ';
			}
		if (minx != _NOCHANGE)
			touchline(win, y, minx, maxx - &win->_y[y][0]);
		startx = 0;
	}
}
Ejemplo n.º 12
0
int wredrawln(WINDOW *win, int beg, int num)
{
int i;

	T((T_CALLED("wredrawln(%p,%d,%d)"), win, beg, num));

	if (touchline(win, beg, num) == OK) {
		size_t len = win->_maxx * sizeof(chtype);

		/*
		 * XSI says that wredrawln() tells the library not to base
		 * optimization on the contents of the lines that are marked.
		 * We do that by changing the contents to nulls after touching
		 * the corresponding lines to get the optimizer's attention.
		 *
		 * FIXME: this won't work if the application makes further
		 * updates before the next refresh.
		 */
		for (i = beg; (i < beg + num) && (i < win->_maxy); i++) {
			memset(win->_line[i].text, 0, len);
		}
	}
	returnCode(OK);
}
Ejemplo n.º 13
0
/*
 * __wgetn_wstr --
 *	The actual implementation.
 *	Note that we include a trailing L'\0' for safety, so str will contain
 *	at most n - 1 other characters.
 */
int
__wgetn_wstr(WINDOW *win, wchar_t *wstr, int n)
{
	wchar_t *ostr, ec, kc, sc[ 2 ];
	int oldx, remain;
	wint_t wc;
	cchar_t cc;

	ostr = wstr;
	if ( erasewchar( &ec ) == ERR )
		return ERR;
	if ( killwchar( &kc ) == ERR )
		return ERR;
	sc[ 0 ] = ( wchar_t )btowc( ' ' );
	sc[ 1 ] = L'\0';
	setcchar( &cc, sc, win->wattr, 0, NULL );
	oldx = win->curx;
	remain = n - 1;

	while (wget_wch(win, &wc) != ERR
	       && wc != L'\n' && wc != L'\r') {
#ifdef DEBUG
		__CTRACE(__CTRACE_INPUT,
		    "__wgetn_wstr: win %p, char 0x%x, remain %d\n",
		    win, wc, remain);
#endif
		*wstr = wc;
		touchline(win, win->cury, 1);
		if (wc == ec || wc == KEY_BACKSPACE || wc == KEY_LEFT) {
			*wstr = L'\0';
			if (wstr != ostr) {
				if ((wchar_t)wc == ec) {
					mvwadd_wch(win, win->cury,
						win->curx, &cc);
					wmove(win, win->cury, win->curx - 1);
				}
				if (wc == KEY_BACKSPACE || wc == KEY_LEFT) {
					/* getch() displays the key sequence */
					mvwadd_wch(win, win->cury,
						win->curx - 1, &cc);
					mvwadd_wch(win, win->cury,
						win->curx - 2, &cc);
					wmove(win, win->cury, win->curx - 1);
				}
				wstr--;
				if (n != -1) {
					/* We're counting chars */
					remain++;
				}
			} else { /* str == ostr */
				if (wc == KEY_BACKSPACE || wc == KEY_LEFT)
					/* getch() displays the other keys */
					mvwadd_wch(win, win->cury,
						win->curx - 1, &cc);
				wmove(win, win->cury, oldx);
			}
		} else if (wc == kc) {
			*wstr = L'\0';
			if (wstr != ostr) {
				/* getch() displays the kill character */
				mvwadd_wch(win, win->cury, win->curx - 1, &cc);
				/* Clear the characters from screen and str */
				while (wstr != ostr) {
					mvwadd_wch(win, win->cury,
						win->curx - 1, &cc);
					wmove(win, win->cury, win->curx - 1);
					wstr--;
					if (n != -1)
						/* We're counting chars */
						remain++;
				}
				mvwadd_wch(win, win->cury, win->curx - 1, &cc);
				wmove(win, win->cury, win->curx - 1);
			} else
				/* getch() displays the kill character */
				mvwadd_wch( win, win->cury, oldx, &cc );
			wmove(win, win->cury, oldx);
		} else if (wc >= KEY_MIN && wc <= KEY_MAX) {
			/* get_wch() displays these characters */
			mvwadd_wch( win, win->cury, win->curx - 1, &cc );
			wmove(win, win->cury, win->curx - 1);
		} else {
			if (remain) {
				wstr++;
				remain--;
			} else {
				mvwadd_wch(win, win->cury, win->curx - 1, &cc);
				wmove(win, win->cury, win->curx - 1);
			}
		}
	}

	if (wc == ERR) {
		*wstr = L'\0';
		return ERR;
	}
	*wstr = L'\0';
	return OK;
}
Ejemplo n.º 14
0
copywin(const WINDOW *src, WINDOW *dst,
	int sminrow, int smincol,
	int dminrow, int dmincol,
	int dmaxrow, int dmaxcol,
	int over)
{
    int rc = ERR;
    int sx, sy, dx, dy;
    bool touched;
    attr_t bk;
    attr_t mask;

    T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"),
       src, dst, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, over));

    if (src && dst) {
	_nc_lock_global(curses);

	bk = AttrOf(dst->_nc_bkgd);
	mask = ~(attr_t) ((bk & A_COLOR) ? A_COLOR : 0);

	/* make sure rectangle exists in source */
	if ((sminrow + dmaxrow - dminrow) <= (src->_maxy + 1) &&
	    (smincol + dmaxcol - dmincol) <= (src->_maxx + 1)) {

	    T(("rectangle exists in source"));

	    /* make sure rectangle fits in destination */
	    if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) {

		T(("rectangle fits in destination"));

		for (dy = dminrow, sy = sminrow;
		     dy <= dmaxrow;
		     sy++, dy++) {

		    touched = FALSE;
		    for (dx = dmincol, sx = smincol;
			 dx <= dmaxcol;
			 sx++, dx++) {
			if (over) {
			    if ((CharOf(src->_line[sy].text[sx]) != L(' ')) &&
				(!CharEq(dst->_line[dy].text[dx],
					 src->_line[sy].text[sx]))) {
				dst->_line[dy].text[dx] =
				    src->_line[sy].text[sx];
				SetAttr(dst->_line[dy].text[dx],
					((AttrOf(src->_line[sy].text[sx]) &
					  mask) | bk));
				touched = TRUE;
			    }
			} else {
			    if (!CharEq(dst->_line[dy].text[dx],
					src->_line[sy].text[sx])) {
				dst->_line[dy].text[dx] =
				    src->_line[sy].text[sx];
				touched = TRUE;
			    }
			}
		    }
		    if (touched) {
			touchline(dst, dminrow, (dmaxrow - dminrow + 1));
		    }
		}
		T(("finished copywin"));
		rc = OK;
	    }
	}
	_nc_unlock_global(curses);
    }
    returnCode(rc);
}
Ejemplo n.º 15
0
/*
 * __wgetnstr --
 *	The actual implementation.
 *	Note that we include a trailing '\0' for safety, so str will contain
 *	at most n - 1 other characters.
 *	XXX: character deletion from screen is based on how the characters
 *	are displayed by wgetch().
 */
int
__wgetnstr(WINDOW *win, char *str, int n)
{
	char *ostr, ec, kc;
	int c, xpos, oldx, remain;

	ostr = str;
	ec = erasechar();
	kc = killchar();
	xpos = oldx = win->curx;
	_DIAGASSERT(n == -1 || n > 1);
	remain = n - 1;

	while ((c = wgetch(win)) != ERR && c != '\n' && c != '\r') {
#ifdef DEBUG
		__CTRACE(__CTRACE_INPUT,
		    "__wgetnstr: win %p, char 0x%x, remain %d\n",
		    win, c, remain);
#endif
		*str = c;
		touchline(win, win->cury, 1);
		if (c == ec || c == KEY_BACKSPACE || c == KEY_LEFT) {
			*str = '\0';
			if (str != ostr) {
				if ((char) c == ec) {
					mvwaddch(win, win->cury, xpos, ' ');
					if (xpos > oldx)
						mvwaddch(win, win->cury,
						    xpos - 1, ' ');
					if (win->curx > xpos - 1)
						wmove(win, win->cury, xpos - 1);
					xpos--;
				}
				if (c == KEY_BACKSPACE || c == KEY_LEFT) {
					/* getch() displays the key sequence */
					mvwaddch(win, win->cury, win->curx,
					    ' ');
					mvwaddch(win, win->cury, win->curx - 1,
					    ' ');
					if (win->curx > xpos)
						wmove(win, win->cury, xpos - 1);
					xpos--;
				}
				str--;
				if (n != -1) {
					/* We're counting chars */
					remain++;
				}
			} else {        /* str == ostr */
				/* getch() displays the other keys */
				if (win->curx > oldx)
					mvwaddch(win, win->cury, win->curx - 1,
					    ' ');
				wmove(win, win->cury, oldx);
				xpos = oldx;
			}
		} else if (c == kc) {
			*str = '\0';
			if (str != ostr) {
				/* getch() displays the kill character */
				mvwaddch(win, win->cury, win->curx - 1, ' ');
				/* Clear the characters from screen and str */
				while (str != ostr) {
					mvwaddch(win, win->cury, win->curx - 1,
					    ' ');
					wmove(win, win->cury, win->curx - 1);
					str--;
					if (n != -1)
						/* We're counting chars */
						remain++;
				}
				mvwaddch(win, win->cury, win->curx - 1, ' ');
				wmove(win, win->cury, win->curx - 1);
			} else
				/* getch() displays the kill character */
				mvwaddch(win, win->cury, oldx, ' ');
			wmove(win, win->cury, oldx);
		} else if (c >= KEY_MIN && c <= KEY_MAX) {
			/* getch() displays these characters */
			mvwaddch(win, win->cury, xpos, ' ');
			wmove(win, win->cury, xpos);
		} else {
			if (remain) {
				if (iscntrl((unsigned char)c))
					mvwaddch(win, win->cury, xpos, ' ');
				str++;
				xpos++;
				remain--;
			} else
				mvwaddch(win, win->cury, xpos, ' ');
			wmove(win, win->cury, xpos);
		}
	}

	if (c == ERR) {
		*str = '\0';
		return (ERR);
	}
	*str = '\0';
	return (OK);
}
Ejemplo n.º 16
0
_nc_scroll_window(WINDOW *win,
		  int const n,
		  int const top,
		  int const bottom,
		  NCURSES_CH_T blank)
{
    int limit;
    int line;
    int j;
    size_t to_copy = (sizeof(NCURSES_CH_T) * (size_t) (win->_maxx + 1));

    TR(TRACE_MOVE, ("_nc_scroll_window(%p, %d, %ld, %ld)",
		    (void *) win, n, (long) top, (long) bottom));

    if (top < 0
	|| bottom < top
	|| bottom > win->_maxy) {
	TR(TRACE_MOVE, ("nothing to scroll"));
	return;
    }

    /*
     * This used to do a line-text pointer-shuffle instead of text copies.
     * That (a) doesn't work when the window is derived and doesn't have
     * its own storage, (b) doesn't save you a lot on modern machines
     * anyway.  Your typical memcpy implementations are coded in
     * assembler using a tight BLT loop; for the size of copies we're
     * talking here, the total execution time is dominated by the one-time
     * setup cost.  So there is no point in trying to be excessively
     * clever -- esr.
     */

    /* shift n lines downwards */
    if (n < 0) {
	limit = top - n;
	for (line = bottom; line >= limit && line >= 0; line--) {
	    TR(TRACE_MOVE, ("...copying %d to %d", line + n, line));
	    memcpy(win->_line[line].text,
		   win->_line[line + n].text,
		   to_copy);
	    if_USE_SCROLL_HINTS(win->_line[line].oldindex =
				win->_line[line + n].oldindex);
	}
	for (line = top; line < limit && line <= win->_maxy; line++) {
	    TR(TRACE_MOVE, ("...filling %d", line));
	    for (j = 0; j <= win->_maxx; j++)
		win->_line[line].text[j] = blank;
	    if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX);
	}
    }

    /* shift n lines upwards */
    if (n > 0) {
	limit = bottom - n;
	for (line = top; line <= limit && line <= win->_maxy; line++) {
	    memcpy(win->_line[line].text,
		   win->_line[line + n].text,
		   to_copy);
	    if_USE_SCROLL_HINTS(win->_line[line].oldindex =
				win->_line[line + n].oldindex);
	}
	for (line = bottom; line > limit && line >= 0; line--) {
	    for (j = 0; j <= win->_maxx; j++)
		win->_line[line].text[j] = blank;
	    if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX);
	}
    }
    touchline(win, top, bottom - top + 1);

    if_WIDEC({
	if (WINDOW_EXT(win, addch_used) != 0) {
	    int next = WINDOW_EXT(win, addch_y) + n;
	    if (next < 0 || next > win->_maxy) {
		TR(TRACE_VIRTPUT,
		   ("Alert discarded multibyte on scroll"));
		WINDOW_EXT(win, addch_y) = 0;
	    } else {
		TR(TRACE_VIRTPUT, ("scrolled working position to %d,%d",
				   WINDOW_EXT(win, addch_y),
				   WINDOW_EXT(win, addch_x)));
		WINDOW_EXT(win, addch_y) = next;
	    }
	}
    })
}
Ejemplo n.º 17
0
int
wscrl(WINDOW *win, int n)
{
int physical = FALSE;
int i;

	T(("wscrl(%x,%d) called", win, n));

	if (! win->_scroll)
		return ERR;

	if (n == 0)
		return OK;

	/* as an optimization, if the scrolling region is the entire screen
	   scroll the physical screen */

	if (   win->_begx == 0 && win->_maxx == columns - 1
	    && !memory_above && !memory_below
	    && ((((win->_begy+win->_regtop == 0 && win->_begy+win->_regbottom == lines - 1)
		  || change_scroll_region)
		 && (   (n < 0 && (parm_rindex || scroll_reverse))
		     || (n > 0 && (parm_index || scroll_forward))
		    )
		) || (win->_idlok && (parm_insert_line || insert_line)
		      && (parm_delete_line || delete_line)
		     )
	       )
	   )
    		physical = TRUE;

	if (physical == TRUE) {
		wrefresh(win);
		scroll_window(curscr, n, win->_begy+win->_regtop, win->_begy+win->_regbottom);
		scroll_window(newscr, n, win->_begy+win->_regtop, win->_begy+win->_regbottom);
	}
	scroll_window(win, n, win->_regtop, win->_regbottom);

	if (physical == TRUE) {
		if (n < 0) {
			if (   ((   win->_begy+win->_regtop == 0
				 && win->_begy+win->_regbottom == lines - 1)
				|| change_scroll_region)
			    && (parm_rindex || scroll_reverse)
			   ) {
				if (change_scroll_region &&
				    (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
				   )
					putp(tparm(change_scroll_region, win->_begy+win->_regtop, win->_begy+win->_regbottom));
				i = abs(n);
				mvcur(-1, -1, win->_begy+win->_regtop, 0);
				if (parm_rindex) {
					putp(tparm(parm_rindex, i));
				} else if (scroll_reverse) {
					while (i--)
						putp(scroll_reverse);
				}
				if (change_scroll_region &&
				    (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
				   )
					putp(tparm(change_scroll_region, 0, lines-1));
			} else {
				i = abs(n);
				if (win->_begy+win->_regbottom < lines - 1) {
					mvcur(-1, -1, win->_begy+win->_regbottom, 0);
					if (parm_delete_line) {
						putp(tparm(parm_delete_line, i));
					} else if (delete_line) {
						while (i--)
							putp(delete_line);
						i = abs(n);
					}
				}
				mvcur(-1, -1, win->_begy+win->_regtop, 0);
				if (parm_insert_line) {
					putp(tparm(parm_insert_line, i));
				} else if (insert_line) {
					while (i--)
						putp(insert_line);
				}
			}
		} else {
			if (   ((   win->_begy+win->_regtop == 0
				 && win->_begy+win->_regbottom == lines - 1)
				|| change_scroll_region)
			    && (parm_index || scroll_forward)
			   ) {
				if (change_scroll_region &&
				    (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
				   )
					putp(tparm(change_scroll_region, win->_begy+win->_regtop, win->_begy+win->_regbottom));
				mvcur(-1, -1, win->_begy+win->_regbottom, 0);
				if (parm_index) {
					putp(tparm(parm_index, n));
				} else if (scroll_forward) {
					i = n;
					while (i--)
						putp(scroll_forward);
				}
				if (change_scroll_region &&
				    (win->_begy+win->_regtop != 0 || win->_begy+win->_regbottom != lines - 1)
				   )
					putp(tparm(change_scroll_region, 0, lines-1));
			} else {
				mvcur(-1, -1, win->_begy+win->_regtop, 0);
				if (parm_delete_line) {
					putp(tparm(parm_delete_line, n));
				} else if (delete_line) {
					i = n;
					while (i--)
						putp(delete_line);
				}
				if (win->_begy+win->_regbottom < lines - 1) {
					mvcur(win->_begy+win->_regtop, 0, win->_begy+win->_regbottom, 0);
					if (parm_insert_line) {
						putp(tparm(parm_insert_line, n));
					} else if (insert_line) {
						i = n;
						while (i--)
							putp(insert_line);
					}
				}
			}
		}

		mvcur(-1, -1, win->_begy+win->_cury, win->_begx+win->_curx);
	} else
	    	touchline(win, win->_regtop, win->_regbottom - win->_regtop + 1);

    	return OK;
}