150276Speter/****************************************************************************
2262629Sdelphij * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc.              *
350276Speter *                                                                          *
450276Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
550276Speter * copy of this software and associated documentation files (the            *
650276Speter * "Software"), to deal in the Software without restriction, including      *
750276Speter * without limitation the rights to use, copy, modify, merge, publish,      *
850276Speter * distribute, distribute with modifications, sublicense, and/or sell       *
950276Speter * copies of the Software, and to permit persons to whom the Software is    *
1050276Speter * furnished to do so, subject to the following conditions:                 *
1150276Speter *                                                                          *
1250276Speter * The above copyright notice and this permission notice shall be included  *
1350276Speter * in all copies or substantial portions of the Software.                   *
1450276Speter *                                                                          *
1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2250276Speter *                                                                          *
2350276Speter * Except as contained in this notice, the name(s) of the above copyright   *
2450276Speter * holders shall not be used in advertising or otherwise to promote the     *
2550276Speter * sale, use or other dealings in this Software without prior written       *
2650276Speter * authorization.                                                           *
2750276Speter ****************************************************************************/
2850276Speter
2950276Speter/****************************************************************************
3050276Speter *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
3150276Speter *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
32262629Sdelphij *     and: Thomas E. Dickey                        1996-on                 *
33262629Sdelphij *     and: Juergen Pfeifer                         2009                    *
3450276Speter ****************************************************************************/
3550276Speter
3650276Speter/*
3750276Speter * lib_pad.c
3850276Speter * newpad	-- create a new pad
3950276Speter * pnoutrefresh -- refresh a pad, no update
4050276Speter * pechochar	-- add a char to a pad and refresh
4150276Speter */
4250276Speter
4350276Speter#include <curses.priv.h>
4450276Speter
45262629SdelphijMODULE_ID("$Id: lib_pad.c,v 1.46 2010/04/24 23:50:45 tom Exp $")
4650276Speter
4776726SpeterNCURSES_EXPORT(WINDOW *)
48262629SdelphijNCURSES_SP_NAME(newpad) (NCURSES_SP_DCLx int l, int c)
4950276Speter{
5062449Speter    WINDOW *win;
5197049Speter    NCURSES_CH_T *ptr;
5262449Speter    int i;
5350276Speter
54262629Sdelphij    T((T_CALLED("newpad(%p,%d, %d)"), (void *) SP_PARM, l, c));
5550276Speter
5662449Speter    if (l <= 0 || c <= 0)
5762449Speter	returnWin(0);
5850276Speter
59262629Sdelphij    win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx l, c, 0, 0, _ISPAD);
60262629Sdelphij    if (win == NULL)
6162449Speter	returnWin(0);
6250276Speter
6362449Speter    for (i = 0; i < l; i++) {
6462449Speter	if_USE_SCROLL_HINTS(win->_line[i].oldindex = _NEWINDEX);
6597049Speter	if ((win->_line[i].text = typeCalloc(NCURSES_CH_T, ((size_t) c))) == 0) {
6676726Speter	    (void) _nc_freewin(win);
6762449Speter	    returnWin(0);
6850276Speter	}
6997049Speter	for (ptr = win->_line[i].text; ptr < win->_line[i].text + c; ptr++)
7097049Speter	    SetChar(*ptr, BLANK_TEXT, BLANK_ATTR);
7162449Speter    }
7250276Speter
7362449Speter    returnWin(win);
7450276Speter}
7550276Speter
76262629Sdelphij#if NCURSES_SP_FUNCS
7776726SpeterNCURSES_EXPORT(WINDOW *)
78262629Sdelphijnewpad(int l, int c)
79262629Sdelphij{
80262629Sdelphij    return NCURSES_SP_NAME(newpad) (CURRENT_SCREEN, l, c);
81262629Sdelphij}
82262629Sdelphij#endif
83262629Sdelphij
84262629SdelphijNCURSES_EXPORT(WINDOW *)
85166124Srafansubpad(WINDOW *orig, int l, int c, int begy, int begx)
8650276Speter{
8762449Speter    WINDOW *win = (WINDOW *) 0;
8850276Speter
8962449Speter    T((T_CALLED("subpad(%d, %d)"), l, c));
9050276Speter
9162449Speter    if (orig) {
9262449Speter	if (!(orig->_flags & _ISPAD)
9362449Speter	    || ((win = derwin(orig, l, c, begy, begx)) == NULL))
9450276Speter	    returnWin(0);
9562449Speter    }
9662449Speter    returnWin(win);
9750276Speter}
9850276Speter
9976726SpeterNCURSES_EXPORT(int)
100166124Srafanprefresh(WINDOW *win,
101166124Srafan	 int pminrow,
102166124Srafan	 int pmincol,
103166124Srafan	 int sminrow,
104166124Srafan	 int smincol,
105166124Srafan	 int smaxrow,
106166124Srafan	 int smaxcol)
10750276Speter{
108262629Sdelphij#if NCURSES_SP_FUNCS
109262629Sdelphij    SCREEN *sp = _nc_screen_of(win);
110262629Sdelphij#endif
111262629Sdelphij
11262449Speter    T((T_CALLED("prefresh()")));
11362449Speter    if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow,
11476726Speter		     smaxcol) != ERR
115262629Sdelphij	&& NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG) != ERR) {
11662449Speter	returnCode(OK);
11762449Speter    }
11862449Speter    returnCode(ERR);
11950276Speter}
12050276Speter
12176726SpeterNCURSES_EXPORT(int)
122166124Srafanpnoutrefresh(WINDOW *win,
123166124Srafan	     int pminrow,
124166124Srafan	     int pmincol,
125166124Srafan	     int sminrow,
126166124Srafan	     int smincol,
127166124Srafan	     int smaxrow,
128166124Srafan	     int smaxcol)
12950276Speter{
130262629Sdelphij    int i, j;
131262629Sdelphij    int m, n;
132262629Sdelphij    int pmaxrow;
133262629Sdelphij    int pmaxcol;
134262629Sdelphij    SCREEN *sp;
13576726Speter
13676726Speter#if USE_SCROLL_HINTS
13776726Speter    const int my_len = 2;	/* parameterize the threshold for hardscroll */
13862449Speter    NCURSES_SIZE_T displaced;
13962449Speter    bool wide;
14076726Speter#endif
14150276Speter
14262449Speter    T((T_CALLED("pnoutrefresh(%p, %d, %d, %d, %d, %d, %d)"),
143262629Sdelphij       (void *) win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol));
14450276Speter
14562449Speter    if (win == 0)
14662449Speter	returnCode(ERR);
14750276Speter
14862449Speter    if (!(win->_flags & _ISPAD))
14962449Speter	returnCode(ERR);
15050276Speter
151262629Sdelphij    sp = _nc_screen_of(win);
152262629Sdelphij
15362449Speter    /* negative values are interpreted as zero */
15462449Speter    if (pminrow < 0)
15562449Speter	pminrow = 0;
15662449Speter    if (pmincol < 0)
15762449Speter	pmincol = 0;
15862449Speter    if (sminrow < 0)
15962449Speter	sminrow = 0;
16062449Speter    if (smincol < 0)
16162449Speter	smincol = 0;
16250276Speter
16362449Speter    pmaxrow = pminrow + smaxrow - sminrow;
16462449Speter    pmaxcol = pmincol + smaxcol - smincol;
16562449Speter
166166124Srafan    T((" pminrow + smaxrow - sminrow %ld, win->_maxy %ld",
167166124Srafan       (long) pmaxrow, (long) win->_maxy));
168166124Srafan    T((" pmincol + smaxcol - smincol %ld, win->_maxx %ld",
169166124Srafan       (long) pmaxcol, (long) win->_maxx));
17062449Speter
17162449Speter    /*
17262449Speter     * Trim the caller's screen size back to the actual limits.
17362449Speter     */
17462449Speter    if (pmaxrow > win->_maxy) {
17562449Speter	smaxrow -= (pmaxrow - win->_maxy);
17650276Speter	pmaxrow = pminrow + smaxrow - sminrow;
17762449Speter    }
17862449Speter    if (pmaxcol > win->_maxx) {
17962449Speter	smaxcol -= (pmaxcol - win->_maxx);
18050276Speter	pmaxcol = pmincol + smaxcol - smincol;
18162449Speter    }
18250276Speter
183262629Sdelphij    if (smaxrow >= screen_lines(sp)
184262629Sdelphij	|| smaxcol >= screen_columns(sp)
18562449Speter	|| sminrow > smaxrow
18662449Speter	|| smincol > smaxcol)
18762449Speter	returnCode(ERR);
18850276Speter
18962449Speter    T(("pad being refreshed"));
19050276Speter
19176726Speter#if USE_SCROLL_HINTS
19262449Speter    if (win->_pad._pad_y >= 0) {
19362449Speter	displaced = pminrow - win->_pad._pad_y
19462449Speter	    - (sminrow - win->_pad._pad_top);
19562449Speter	T(("pad being shifted by %d line(s)", displaced));
19662449Speter    } else
19762449Speter	displaced = 0;
19876726Speter#endif
19950276Speter
20062449Speter    /*
20162449Speter     * For pure efficiency, we'd want to transfer scrolling information
20262449Speter     * from the pad to newscr whenever the window is wide enough that
20362449Speter     * its update will dominate the cost of the update for the horizontal
20462449Speter     * band of newscr that it occupies.  Unfortunately, this threshold
20562449Speter     * tends to be complex to estimate, and in any case scrolling the
20662449Speter     * whole band and rewriting the parts outside win's image would look
20762449Speter     * really ugly.  So.  What we do is consider the pad "wide" if it
20862449Speter     * either (a) occupies the whole width of newscr, or (b) occupies
20962449Speter     * all but at most one column on either vertical edge of the screen
21062449Speter     * (this caters to fussy people who put boxes around full-screen
21162449Speter     * windows).  Note that changing this formula will not break any code,
21262449Speter     * merely change the costs of various update cases.
21362449Speter     */
21476726Speter#if USE_SCROLL_HINTS
215262629Sdelphij    wide = (smincol < my_len && smaxcol > (NewScreen(sp)->_maxx - my_len));
21676726Speter#endif
21750276Speter
21862449Speter    for (i = pminrow, m = sminrow + win->_yoffset;
219262629Sdelphij	 i <= pmaxrow && m <= NewScreen(sp)->_maxy;
22076726Speter	 i++, m++) {
221262629Sdelphij	register struct ldat *nline = &NewScreen(sp)->_line[m];
22262449Speter	register struct ldat *oline = &win->_line[i];
22398503Speter	for (j = pmincol, n = smincol; j <= pmaxcol; j++, n++) {
22498503Speter	    NCURSES_CH_T ch = oline->text[j];
22598503Speter#if USE_WIDEC_SUPPORT
22698503Speter	    /*
22798503Speter	     * Special case for leftmost character of the displayed area.
22898503Speter	     * Only half of a double-width character may be visible.
22998503Speter	     */
23098503Speter	    if (j == pmincol
23198503Speter		&& j > 0
232166124Srafan		&& isWidecExt(ch)) {
23398503Speter		SetChar(ch, L(' '), AttrOf(oline->text[j - 1]));
23498503Speter	    }
23598503Speter#endif
23698503Speter	    if (!CharEq(ch, nline->text[n])) {
23798503Speter		nline->text[n] = ch;
23862449Speter		CHANGED_CELL(nline, n);
23962449Speter	    }
24062449Speter	}
24150276Speter
24250276Speter#if USE_SCROLL_HINTS
24362449Speter	if (wide) {
24462449Speter	    int nind = m + displaced;
24562449Speter	    if (oline->oldindex < 0
24662449Speter		|| nind < sminrow
24762449Speter		|| nind > smaxrow) {
24862449Speter		nind = _NEWINDEX;
24962449Speter	    } else if (displaced) {
250262629Sdelphij		register struct ldat *pline = &CurScreen(sp)->_line[nind];
25162449Speter		for (j = 0; j <= my_len; j++) {
252262629Sdelphij		    int k = NewScreen(sp)->_maxx - j;
25362449Speter		    if (pline->text[j] != nline->text[j]
25462449Speter			|| pline->text[k] != nline->text[k]) {
25550276Speter			nind = _NEWINDEX;
25662449Speter			break;
25750276Speter		    }
25862449Speter		}
25962449Speter	    }
26050276Speter
26162449Speter	    nline->oldindex = nind;
26262449Speter	}
26350276Speter#endif /* USE_SCROLL_HINTS */
26462449Speter	oline->firstchar = oline->lastchar = _NOCHANGE;
26562449Speter	if_USE_SCROLL_HINTS(oline->oldindex = i);
26662449Speter    }
26750276Speter
26862449Speter    /*
26962449Speter     * Clean up debris from scrolling or resizing the pad, so we do not
27062449Speter     * accidentally pick up the index value during the next call to this
27162449Speter     * procedure.  The only rows that should have an index value are those
27262449Speter     * that are displayed during this cycle.
27362449Speter     */
27450276Speter#if USE_SCROLL_HINTS
27562449Speter    for (i = pminrow - 1; (i >= 0) && (win->_line[i].oldindex >= 0); i--)
27662449Speter	win->_line[i].oldindex = _NEWINDEX;
27762449Speter    for (i = pmaxrow + 1; (i <= win->_maxy)
27876726Speter	 && (win->_line[i].oldindex >= 0); i++)
27962449Speter	win->_line[i].oldindex = _NEWINDEX;
28050276Speter#endif
28150276Speter
282262629Sdelphij    win->_begx = (NCURSES_SIZE_T) smincol;
283262629Sdelphij    win->_begy = (NCURSES_SIZE_T) sminrow;
28450276Speter
28562449Speter    if (win->_clear) {
28662449Speter	win->_clear = FALSE;
287262629Sdelphij	NewScreen(sp)->_clear = TRUE;
28862449Speter    }
28950276Speter
29062449Speter    /*
29162449Speter     * Use the pad's current position, if it will be visible.
29262449Speter     * If not, don't do anything; it's not an error.
29362449Speter     */
29462449Speter    if (win->_leaveok == FALSE
29562449Speter	&& win->_cury >= pminrow
29662449Speter	&& win->_curx >= pmincol
29762449Speter	&& win->_cury <= pmaxrow
29862449Speter	&& win->_curx <= pmaxcol) {
299262629Sdelphij	NewScreen(sp)->_cury = (NCURSES_SIZE_T) (win->_cury - pminrow
300262629Sdelphij						 + win->_begy + win->_yoffset);
301262629Sdelphij	NewScreen(sp)->_curx = (NCURSES_SIZE_T) (win->_curx - pmincol
302262629Sdelphij						 + win->_begx);
30362449Speter    }
304262629Sdelphij    NewScreen(sp)->_leaveok = win->_leaveok;
30562449Speter    win->_flags &= ~_HASMOVED;
30650276Speter
30762449Speter    /*
30862449Speter     * Update our cache of the line-numbers that we displayed from the pad.
30962449Speter     * We will use this on subsequent calls to this function to derive
31062449Speter     * values to stuff into 'oldindex[]' -- for scrolling optimization.
31162449Speter     */
312262629Sdelphij    win->_pad._pad_y = (NCURSES_SIZE_T) pminrow;
313262629Sdelphij    win->_pad._pad_x = (NCURSES_SIZE_T) pmincol;
314262629Sdelphij    win->_pad._pad_top = (NCURSES_SIZE_T) sminrow;
315262629Sdelphij    win->_pad._pad_left = (NCURSES_SIZE_T) smincol;
316262629Sdelphij    win->_pad._pad_bottom = (NCURSES_SIZE_T) smaxrow;
317262629Sdelphij    win->_pad._pad_right = (NCURSES_SIZE_T) smaxcol;
31850276Speter
31962449Speter    returnCode(OK);
32050276Speter}
32150276Speter
32276726SpeterNCURSES_EXPORT(int)
32362449Speterpechochar(WINDOW *pad, const chtype ch)
32450276Speter{
325262629Sdelphij    T((T_CALLED("pechochar(%p, %s)"), (void *) pad, _tracechtype(ch)));
32650276Speter
32762449Speter    if (pad == 0)
32862449Speter	returnCode(ERR);
32950276Speter
33062449Speter    if (!(pad->_flags & _ISPAD))
33162449Speter	returnCode(wechochar(pad, ch));
33250276Speter
33362449Speter    waddch(pad, ch);
33462449Speter    prefresh(pad, pad->_pad._pad_y,
33576726Speter	     pad->_pad._pad_x,
33676726Speter	     pad->_pad._pad_top,
33776726Speter	     pad->_pad._pad_left,
33876726Speter	     pad->_pad._pad_bottom,
33976726Speter	     pad->_pad._pad_right);
34062449Speter
34162449Speter    returnCode(OK);
34250276Speter}
343