]> ncurses.scripts.mit.edu Git - ncurses.git/blob - ncurses/lib_pad.c
ncurses 4.1
[ncurses.git] / ncurses / lib_pad.c
1
2 /***************************************************************************
3 *                            COPYRIGHT NOTICE                              *
4 ****************************************************************************
5 *                ncurses is copyright (C) 1992-1995                        *
6 *                          Zeyd M. Ben-Halim                               *
7 *                          zmbenhal@netcom.com                             *
8 *                          Eric S. Raymond                                 *
9 *                          esr@snark.thyrsus.com                           *
10 *                                                                          *
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.                *
17 *                                                                          *
18 *        ncurses comes AS IS with no warranty, implied or expressed.       *
19 *                                                                          *
20 ***************************************************************************/
21
22
23 /*
24  * lib_pad.c
25  * newpad       -- create a new pad
26  * pnoutrefresh -- refresh a pad, no update
27  * pechochar    -- add a char to a pad and refresh
28  */
29
30 #include <curses.priv.h>
31
32 MODULE_ID("$Id: lib_pad.c,v 1.18 1997/04/12 17:42:52 tom Exp $")
33
34 WINDOW *newpad(int l, int c)
35 {
36 WINDOW *win;
37 chtype *ptr;
38 int i;
39
40         T((T_CALLED("newpad(%d, %d)"), l, c));
41
42         if (l <= 0 || c <= 0)
43                 returnWin(0);
44
45         if ((win = _nc_makenew(l,c,0,0,_ISPAD)) == NULL)
46                 returnWin(0);
47
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) {
51                 _nc_freewin(win);
52                 returnWin(0);
53             }
54             for (ptr = win->_line[i].text; ptr < win->_line[i].text + c; )
55                 *ptr++ = ' ';
56         }
57
58         returnWin(win);
59 }
60
61 WINDOW *subpad(WINDOW *orig, int l, int c, int begy, int begx)
62 {
63 WINDOW  *win;
64
65         T((T_CALLED("subpad(%d, %d)"), l, c));
66
67         if (!(orig->_flags & _ISPAD) || ((win = derwin(orig, l, c, begy, begx)) == NULL))
68             returnWin(0);
69
70         returnWin(win);
71 }
72
73 int prefresh(WINDOW *win, int pminrow, int pmincol,
74         int sminrow, int smincol, int smaxrow, int smaxcol)
75 {
76         T((T_CALLED("prefresh()")));
77         if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol) != ERR
78          && doupdate() != ERR) {
79                 returnCode(OK);
80         }
81         returnCode(ERR);
82 }
83
84 int pnoutrefresh(WINDOW *win, int pminrow, int pmincol,
85         int sminrow, int smincol, int smaxrow, int smaxcol)
86 {
87 short   i, j;
88 short   m, n;
89 short   pmaxrow;
90 short   pmaxcol;
91 short   displaced;
92 bool    wide;
93
94         T((T_CALLED("pnoutrefresh(%p, %d, %d, %d, %d, %d, %d)"),
95                 win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol));
96
97         if (win == 0)
98                 returnCode(ERR);
99
100         if (!(win->_flags & _ISPAD))
101                 returnCode(ERR);
102
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;
108
109         pmaxrow = pminrow + smaxrow - sminrow;
110         pmaxcol = pmincol + smaxcol - smincol;
111
112         T((" pminrow + smaxrow - sminrow %d, win->_maxy %d", pmaxrow, win->_maxy));
113         T((" pmincol + smaxcol - smincol %d, win->_maxx %d", pmaxcol, win->_maxx));
114
115         /*
116          * Trim the caller's screen size back to the actual limits.
117          */
118         if (pmaxrow > win->_maxy) {
119                 smaxrow -= (pmaxrow - win->_maxy);
120                 pmaxrow = pminrow + smaxrow - sminrow;
121         }
122         if (pmaxcol > win->_maxx) {
123                 smaxcol -= (pmaxcol - win->_maxx);
124                 pmaxcol = pmincol + smaxcol - smincol;
125         }
126
127         if (smaxrow > screen_lines
128          || smaxcol > screen_columns
129          || sminrow > smaxrow
130          || smincol > smaxcol)
131                 returnCode(ERR);
132
133         T(("pad being refreshed"));
134
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));
139         } else
140                 displaced = 0;
141
142         /*
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.
155          */
156         wide = (sminrow <= 1 && win->_maxx >= (newscr->_maxx - 1));
157
158         for (i = pminrow, m = sminrow + win->_yoffset;
159                 i <= pmaxrow && m <= newscr->_maxy;
160                         i++, m++) {
161                 register struct ldat    *nline = &newscr->_line[m];
162                 register struct ldat    *oline = &win->_line[i];
163
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];
167
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)
173                                         nline->lastchar = n;
174                         }
175                 }
176
177                 if (wide) {
178                     int nind = m + displaced;
179                     if (oline->oldindex < 0
180                      || nind < sminrow
181                      || nind > smaxrow)
182                         nind = _NEWINDEX;
183
184                     nline->oldindex = nind;
185                 }
186                 oline->firstchar = oline->lastchar = _NOCHANGE;
187                 oline->oldindex = i;
188         }
189
190         /*
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.
195          */
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;
200
201         win->_begx = smincol;
202         win->_begy = sminrow;
203
204         if (win->_clear) {
205             win->_clear = FALSE;
206             newscr->_clear = TRUE;
207         }
208
209         /*
210          * Use the pad's current position, if it will be visible.
211          * If not, don't do anything; it's not an error.
212          */
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;
220         }
221         win->_flags &= ~_HASMOVED;
222
223         /*
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.
227          */
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;
234
235         returnCode(OK);
236 }
237
238 int pechochar(WINDOW *pad, chtype ch)
239 {
240         T((T_CALLED("pechochar(%p, %s)"), pad, _tracechtype(ch)));
241
242         if (pad->_flags & _ISPAD)
243                 returnCode(ERR);
244
245         waddch(curscr, ch);
246         doupdate();
247         returnCode(OK);
248 }