2 /***************************************************************************
4 ****************************************************************************
5 * ncurses is copyright (C) 1992-1995 *
7 * zmbenhal@netcom.com *
9 * esr@snark.thyrsus.com *
11 * Permission is hereby granted to reproduce and distribute ncurses *
12 * by any means and for any fee, whether alone or as part of a *
13 * larger distribution, in source or in binary form, PROVIDED *
14 * this notice is included with any such distribution, and is not *
15 * removed from any of its header files. Mention of ncurses in any *
16 * applications linked with it is highly appreciated. *
18 * ncurses comes AS IS with no warranty, implied or expressed. *
20 ***************************************************************************/
25 * newpad -- create a new pad
26 * pnoutrefresh -- refresh a pad, no update
27 * pechochar -- add a char to a pad and refresh
30 #include <curses.priv.h>
32 MODULE_ID("$Id: lib_pad.c,v 1.18 1997/04/12 17:42:52 tom Exp $")
34 WINDOW *newpad(int l, int c)
40 T((T_CALLED("newpad(%d, %d)"), l, c));
45 if ((win = _nc_makenew(l,c,0,0,_ISPAD)) == NULL)
48 for (i = 0; i < l; i++) {
49 win->_line[i].oldindex = _NEWINDEX;
50 if ((win->_line[i].text = typeCalloc(chtype, ((size_t)c))) == 0) {
54 for (ptr = win->_line[i].text; ptr < win->_line[i].text + c; )
61 WINDOW *subpad(WINDOW *orig, int l, int c, int begy, int begx)
65 T((T_CALLED("subpad(%d, %d)"), l, c));
67 if (!(orig->_flags & _ISPAD) || ((win = derwin(orig, l, c, begy, begx)) == NULL))
73 int prefresh(WINDOW *win, int pminrow, int pmincol,
74 int sminrow, int smincol, int smaxrow, int smaxcol)
76 T((T_CALLED("prefresh()")));
77 if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol) != ERR
78 && doupdate() != ERR) {
84 int pnoutrefresh(WINDOW *win, int pminrow, int pmincol,
85 int sminrow, int smincol, int smaxrow, int smaxcol)
94 T((T_CALLED("pnoutrefresh(%p, %d, %d, %d, %d, %d, %d)"),
95 win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol));
100 if (!(win->_flags & _ISPAD))
103 /* negative values are interpreted as zero */
104 if (pminrow < 0) pminrow = 0;
105 if (pmincol < 0) pmincol = 0;
106 if (sminrow < 0) sminrow = 0;
107 if (smincol < 0) smincol = 0;
109 pmaxrow = pminrow + smaxrow - sminrow;
110 pmaxcol = pmincol + smaxcol - smincol;
112 T((" pminrow + smaxrow - sminrow %d, win->_maxy %d", pmaxrow, win->_maxy));
113 T((" pmincol + smaxcol - smincol %d, win->_maxx %d", pmaxcol, win->_maxx));
116 * Trim the caller's screen size back to the actual limits.
118 if (pmaxrow > win->_maxy) {
119 smaxrow -= (pmaxrow - win->_maxy);
120 pmaxrow = pminrow + smaxrow - sminrow;
122 if (pmaxcol > win->_maxx) {
123 smaxcol -= (pmaxcol - win->_maxx);
124 pmaxcol = pmincol + smaxcol - smincol;
127 if (smaxrow > screen_lines
128 || smaxcol > screen_columns
130 || smincol > smaxcol)
133 T(("pad being refreshed"));
135 if (win->_pad._pad_y >= 0) {
136 displaced = pminrow - win->_pad._pad_y
137 -(sminrow - win->_pad._pad_top);
138 T(("pad being shifted by %d line(s)", displaced));
143 * For pure efficiency, we'd want to transfer scrolling information
144 * from the pad to newscr whenever the window is wide enough that
145 * its update will dominate the cost of the update for the horizontal
146 * band of newscr that it occupies. Unfortunately, this threshold
147 * tends to be complex to estimate, and in any case scrolling the
148 * whole band and rewriting the parts outside win's image would look
149 * really ugly. So. What we do is consider the pad "wide" if it
150 * either (a) occupies the whole width of newscr, or (b) occupies
151 * all but at most one column on either vertical edge of the screen
152 * (this caters to fussy people who put boxes around full-screen
153 * windows). Note that changing this formula will not break any code,
154 * merely change the costs of various update cases.
156 wide = (sminrow <= 1 && win->_maxx >= (newscr->_maxx - 1));
158 for (i = pminrow, m = sminrow + win->_yoffset;
159 i <= pmaxrow && m <= newscr->_maxy;
161 register struct ldat *nline = &newscr->_line[m];
162 register struct ldat *oline = &win->_line[i];
164 for (j = pmincol, n = smincol; j <= pmaxcol; j++, n++) {
165 if (oline->text[j] != nline->text[n]) {
166 nline->text[n] = oline->text[j];
168 if (nline->firstchar == _NOCHANGE)
169 nline->firstchar = nline->lastchar = n;
170 else if (n < nline->firstchar)
171 nline->firstchar = n;
172 else if (n > nline->lastchar)
178 int nind = m + displaced;
179 if (oline->oldindex < 0
184 nline->oldindex = nind;
186 oline->firstchar = oline->lastchar = _NOCHANGE;
191 * Clean up debris from scrolling or resizing the pad, so we do not
192 * accidentally pick up the index value during the next call to this
193 * procedure. The only rows that should have an index value are those
194 * that are displayed during this cycle.
196 for (i = pminrow-1; (i >= 0) && (win->_line[i].oldindex >= 0); i--)
197 win->_line[i].oldindex = _NEWINDEX;
198 for (i = pmaxrow+1; (i <= win->_maxy) && (win->_line[i].oldindex >= 0); i++)
199 win->_line[i].oldindex = _NEWINDEX;
201 win->_begx = smincol;
202 win->_begy = sminrow;
206 newscr->_clear = TRUE;
210 * Use the pad's current position, if it will be visible.
211 * If not, don't do anything; it's not an error.
213 if (win->_leaveok == FALSE
214 && win->_cury >= pminrow
215 && win->_curx >= pmincol
216 && win->_cury <= pmaxrow
217 && win->_curx <= pmaxcol) {
218 newscr->_cury = win->_cury - pminrow + win->_begy + win->_yoffset;
219 newscr->_curx = win->_curx - pmincol + win->_begx;
221 win->_flags &= ~_HASMOVED;
224 * Update our cache of the line-numbers that we displayed from the pad.
225 * We will use this on subsequent calls to this function to derive
226 * values to stuff into 'oldindex[]' -- for scrolling optimization.
228 win->_pad._pad_y = pminrow;
229 win->_pad._pad_x = pmincol;
230 win->_pad._pad_top = sminrow;
231 win->_pad._pad_left = smincol;
232 win->_pad._pad_bottom = smaxrow;
233 win->_pad._pad_right = smaxcol;
238 int pechochar(WINDOW *pad, chtype ch)
240 T((T_CALLED("pechochar(%p, %s)"), pad, _tracechtype(ch)));
242 if (pad->_flags & _ISPAD)