ncurses 4.1
[ncurses.git] / ncurses / lib_refresh.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 /*
25  *      lib_refresh.c
26  *
27  *      The routines wredrawln(), wrefresh() and wnoutrefresh().
28  *
29  */
30
31 #include <curses.priv.h>
32
33 MODULE_ID("$Id: lib_refresh.c,v 1.14 1997/02/02 01:05:26 tom Exp $")
34
35 int wredrawln(WINDOW *win, int beg, int num)
36 {
37         T((T_CALLED("wredrawln(%p,%d,%d)"), win, beg, num));
38         touchline(win, beg, num);
39         wrefresh(win);
40         returnCode(OK);
41 }
42
43 int wrefresh(WINDOW *win)
44 {
45 int code;
46
47         T((T_CALLED("wrefresh(%p)"), win));
48
49         if (win == curscr) {
50                 curscr->_clear = TRUE;
51                 code = doupdate();
52         } else if ((code = wnoutrefresh(win)) == OK) {
53                 if (win->_clear)
54                         newscr->_clear = TRUE;
55                 code = doupdate();
56                 /*
57                  * Reset the clearok() flag in case it was set for the special
58                  * case in hardscroll.c (if we don't reset it here, we'll get 2
59                  * refreshes because the flag is copied from stdscr to newscr).
60                  * Resetting the flag shouldn't do any harm, anyway.
61                  */
62                 win->_clear = FALSE;
63         }
64         returnCode(code);
65 }
66
67 int wnoutrefresh(WINDOW *win)
68 {
69 short   i, j;
70 short   begx = win->_begx;
71 short   begy = win->_begy;
72 short   m, n;
73 bool    wide;
74
75         T((T_CALLED("wnoutrefresh(%p)"), win));
76 #ifdef TRACE
77         if (_nc_tracing & TRACE_UPDATE)
78             _tracedump("...win", win);
79 #endif /* TRACE */
80
81         /*
82          * This function will break badly if we try to refresh a pad.
83          */
84         if ((win == 0)
85          || (win->_flags & _ISPAD))
86                 returnCode(ERR);
87
88         /*
89          * If 'newscr' has a different background than the window that we're
90          * trying to refresh, we'll have to copy the whole thing.
91          */
92         if (win->_bkgd != newscr->_bkgd) {
93                 touchwin(win);
94                 newscr->_bkgd = win->_bkgd;
95         }
96         newscr->_attrs = win->_attrs;
97
98         /* merge in change information from all subwindows of this window */
99         wsyncdown(win);
100
101         /*
102          * For pure efficiency, we'd want to transfer scrolling information
103          * from the window to newscr whenever the window is wide enough that
104          * its update will dominate the cost of the update for the horizontal
105          * band of newscr that it occupies.  Unfortunately, this threshold
106          * tends to be complex to estimate, and in any case scrolling the
107          * whole band and rewriting the parts outside win's image would look
108          * really ugly.  So.  What we do is consider the window "wide" if it
109          * either (a) occupies the whole width of newscr, or (b) occupies
110          * all but at most one column on either vertical edge of the screen
111          * (this caters to fussy people who put boxes around full-screen
112          * windows).  Note that changing this formula will not break any code,
113          * merely change the costs of various update cases.
114          */
115         wide = (begx <= 1 && win->_maxx >= (newscr->_maxx - 1));
116
117         win->_flags &= ~_HASMOVED;
118
119         /*
120          * Microtweaking alert!  This double loop is one of the genuine
121          * hot spots in the code.  Even gcc doesn't seem to do enough
122          * common-subexpression chunking to make it really tense,
123          * so we'll force the issue.
124          */
125         for (i = 0, m = begy + win->_yoffset;
126              i <= win->_maxy && m <= newscr->_maxy;
127              i++, m++) {
128                 register struct ldat    *nline = &newscr->_line[m];
129                 register struct ldat    *oline = &win->_line[i];
130
131                 if (oline->firstchar != _NOCHANGE) {
132                         int last = oline->lastchar;
133
134                         /* limit(j) */
135                         if (last > win->_maxx)
136                                 last = win->_maxx;
137                         /* limit(n) */
138                         if (last > newscr->_maxx - begx)
139                                 last = newscr->_maxx - begx;
140
141                         for (j = oline->firstchar, n = j + begx; j <= last; j++, n++) {
142                                 if (oline->text[j] != nline->text[n]) {
143                                         nline->text[n] = oline->text[j];
144
145                                         if (nline->firstchar == _NOCHANGE)
146                                                 nline->firstchar = nline->lastchar = n;
147                                         else if (n < nline->firstchar)
148                                                 nline->firstchar = n;
149                                         else if (n > nline->lastchar)
150                                                 nline->lastchar = n;
151                                 }
152                         }
153
154                 }
155
156                 if (wide) {
157                     int oind = oline->oldindex;
158
159                     nline->oldindex = (oind == _NEWINDEX) ? _NEWINDEX : begy + oind + win->_yoffset;
160                 }
161
162                 oline->firstchar = oline->lastchar = _NOCHANGE;
163                 oline->oldindex = i;
164         }
165
166         if (win->_clear) {
167                 win->_clear = FALSE;
168                 newscr->_clear = TRUE;
169         }
170
171         if (! win->_leaveok) {
172                 newscr->_cury = win->_cury + win->_begy + win->_yoffset;
173                 newscr->_curx = win->_curx + win->_begx;
174         }
175 #ifdef TRACE
176         if (_nc_tracing & TRACE_UPDATE)
177             _tracedump("newscr", newscr);
178 #endif /* TRACE */
179         returnCode(OK);
180 }