1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1995-1998 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 /* LINTLIBRARY */
28
29 /*
30 * wrefresh.c
31 *
32 * XCurses Library
33 *
34 * Copyright 1990, 1995 by Mortice Kern Systems Inc. All rights reserved.
35 *
36 */
37
38 #ifdef M_RCSID
39 #ifndef lint
40 static char rcsID[] =
41 "$Header: /team/ps/sun_xcurses/archive/local_changes/xcurses/src/lib/"
42 "libxcurses/src/libc/xcurses/rcs/wrefresh.c 1.7 1998/06/04 17:52:06 "
43 "cbates Exp $";
44 #endif
45 #endif
46
47 #include <private.h>
48 #include <string.h>
49
50 /*
51 * Update curscr with the given window then display to the terminal.
52 * Unless leaveok() has been enabled, the physical cursor of the
53 * terminal is left at the location of the cursor for that window.
54 */
55 int
wrefresh(WINDOW * w)56 wrefresh(WINDOW *w)
57 {
58 int value;
59
60 if (w == curscr)
61 value = clearok(__m_screen->_newscr, TRUE);
62 else
63 value = wnoutrefresh(w);
64
65 if (value == OK)
66 value = doupdate();
67
68 return (value);
69 }
70
71 /*
72 * Update newscr with the given window. This allows newscr to be
73 * updated with several windows before doing a doupdate() (and so
74 * improve the efficiency of multiple updates in comparison to
75 * looping through wrefresh() for all windows).
76 */
77 int
wnoutrefresh(WINDOW * w)78 wnoutrefresh(WINDOW *w)
79 {
80 int wy, wx, ny, nx, dx, value;
81 WINDOW *ns = __m_screen->_newscr;
82
83 /* Kluge to make test suite happy ... */
84 if (w == stdscr)
85 (void) slk_noutrefresh();
86
87 value = (w->_flags & W_IS_PAD) ? ERR : OK;
88
89 if (value == OK) {
90 /*
91 * This loop is similar to what copywin() does, except that
92 * this loop only copies dirty lines, while copywin() copies
93 * every line.
94 */
95 for (wy = 0, ny = w->_begy; wy < w->_maxy; ++wy, ++ny) {
96 /* Has line been touched? */
97 if (w->_last[wy] <= w->_first[wy])
98 continue;
99
100 wx = w->_first[wy];
101 nx = w->_begx + wx;
102 dx = w->_last[wy] - wx;
103
104 /*
105 * Case 3 - Check target window for overlap of broad
106 * characters around the outer edge of the source
107 * window's location.
108 */
109 (void) memcpy(&ns->_line[ny][nx], &w->_line[wy][wx],
110 dx * sizeof (**w->_line));
111
112 /* Make destination dirtier */
113 if (ns->_first[ny] > nx)
114 ns->_first[ny] = (short) nx;
115
116 if (ns->_last[ny] < (nx + dx))
117 ns->_last[ny] = (short) (nx + dx);
118
119 if (!ns->_line[ny][nx]._f) {
120 /*
121 * Case 5 - Incomplete glyph copied from
122 * source at screen margins.
123 */
124 if (nx <= 0)
125 (void) __m_cc_erase(ns, ny, 0, ny, 0);
126 #ifdef M_CURSES_SENSIBLE_WINDOWS
127 /*
128 * Case 4 - Expand incomplete glyph from
129 * source into target window.
130 */
131 else if (0 < nx)
132 (void) __m_cc_expand(ns, ny, nx, -1);
133 #endif /* M_CURSES_SENSIBLE_WINDOWS */
134 }
135
136 if (!__m_cc_islast(ns, ny, nx+dx-1)) {
137 /*
138 * Case 5 - Incomplete glyph copied from
139 * source at screen margins.
140 */
141 if (ns->_maxx <= nx + dx)
142 (void) __m_cc_erase(ns, ny, nx + dx - 1,
143 ny, nx + dx - 1);
144 #ifdef M_CURSES_SENSIBLE_WINDOWS
145 /*
146 * Case 4 - Expand incomplete glyph from
147 * source into target window.
148 */
149 else if (nx + dx < ns->_maxx)
150 (void) __m_cc_expand(ns, ny,
151 nx + dx - 1, 1);
152 #endif /* M_CURSES_SENSIBLE_WINDOWS */
153 }
154
155 /* Untouch line. */
156 w->_first[wy] = w->_maxx;
157 w->_last[wy] = -1;
158
159 /* Remember refresh region (inclusive). */
160 w->_refy = w->_begy;
161 w->_refx = w->_begx;
162 w->_sminy = w->_sminx = 0;
163 w->_smaxy = ns->_maxy - 1;
164 w->_smaxx = ns->_maxx - 1;
165 }
166
167 ns->_scroll = w->_scroll;
168 w->_scroll = 0;
169
170 /* Last refreshed window controls W_LEAVE_CURSOR flag. */
171 ns->_flags &= ~W_LEAVE_CURSOR;
172 ns->_cury = w->_cury + w->_begy;
173 ns->_curx = w->_curx + w->_begx;
174
175 ns->_flags |= w->_flags &
176 (W_CLEAR_WINDOW | W_REDRAW_WINDOW | W_LEAVE_CURSOR);
177 w->_flags &= ~(W_CLEAR_WINDOW | W_REDRAW_WINDOW);
178 }
179
180 return (value);
181 }
182
183 /*
184 * Check overlaping region on a line.
185 *
186 * When copying a source window region over another target window
187 * region, we have a few cases which to concern ourselves with.
188 *
189 * Let {, [, ( and ), ], } denote the left and right halves of
190 * broad glyphes.
191 *
192 * Let alpha-numerics and periods (.) be narrow glyphes.
193 *
194 * Let hash (#) be a narrow background character.
195 *
196 * Let vertical bar, hyphen, and plus represent the borders
197 * of a window.
198 *
199 * 1. Copy narrow characters over narrow characters.
200 * copywin(s, t, 0, 1, 0, 1, 1, 3, 0)
201 * s t ==> t
202 * +------+ +------+ +------+
203 * |abcdef| |......| |.bcd..|
204 * |ghijkl| |......| |.hij..|
205 * |mnopqr| |......| |......|
206 * +------+ +------+ +------+
207 * Nothing special.
208 *
209 * 2. Copy whole broad characters over narrow characters.
210 * copywin(s, t, 0, 1, 0, 1, 1, 3, 0)
211 * s t ==> t
212 * +------+ +------+ +------+
213 * |a[]def| |......| |.[]d..|
214 * |gh{}kl| |......| |.h{}..|
215 * |mnopqr| |......| |......|
216 * +------+ +------+ +------+
217 * Nothing special.
218 *
219 * 3. Copy narrow from source overlaps broad in target.
220 * copywin(s, t, 0, 1, 0, 1, 1, 3, 0)
221 * s t ==> t
222 * +------+ +------+ +------+
223 * |abcdef| |[]....| |#bcd..|
224 * |ghijkl| |...{}.| |.hij#.|
225 * |mnopqr| |......| |......|
226 * +------+ +------+ +------+
227 * The # background characters have wiped out the remaining
228 * halves of broad characters. This may result also with
229 * a wnoutrefresh() of a window onto curscr.
230 *
231 * The following case appears to be disallowed in XPG4 V2
232 * and I think they're wrong, so I've conditionalised the code
233 * on M_CURSES_SENSIBLE_WINDOWS.
234 *
235 * 4. Copy incomplete broad from source to target.
236 * copywin(s, t, 0, 1, 0, 1, 1, 3, 0)
237 * s t ==> t
238 * +------+ +------+ +------+
239 * |[]cdef| |123456| |[]cd56|
240 * |ghi{}l| |789012| |7hi{}2|
241 * |mnopqr| |......| |......|
242 * +------+ +------+ +------+
243 * The ] and { halves of broad characters have been copied and
244 * expanded into the target outside of the specified target region.
245 * This may result also with a wnoutrefresh() of a window onto
246 * curscr.
247 *
248 * Consider a pop-up dialog that contains narrow characters and
249 * a base window that contains broad characters and we do the
250 * following:
251 *
252 * save = dupwin(dialog); // create backing store
253 * overwrite(curscr, save); // save region to be overlayed
254 * wrefresh(dialog); // display dialog
255 * ... // do dialog stuff
256 * wrefresh(save); // restore screen image
257 * delwin(save); // release backing store
258 *
259 * Code similar to this has been used to implement generic popup()
260 * and popdown() routines. In the simple case where the base window
261 * contains narrow characters only, it would be correctly restored.
262 *
263 * However with broad characters, the overwrite() could copy a
264 * region with incomplete broad characters. The wrefresh(dialog)
265 * results in case 3. In order to restore the window correctly with
266 * wrefresh(save), we require case 4.
267 *
268 * 5. Copy incomplete broad from source to target region next to margin.
269 *
270 * a)
271 * copywin(s, t, 0, 1, 0, 0, 1, 2, 0)
272 * s t ==> t
273 * +------+ +------+ +------+
274 * |[]cdef| |123456| |#cd456|
275 * |ghijkl| |789012| |hij012|
276 * |mnopqr| |......| |......|
277 * +------+ +------+ +------+
278 * The # background character has replaced the ] character that
279 * would have been copied from the source, because it is not possible
280 * to expand the broad character to its complete form (case 4).
281 *
282 * b)
283 * copywin(s, t, 0, 1, 0, 3, 1, 5, 0)
284 * s t ==> t
285 * +------+ +------+ +------+
286 * |abcdef| |123456| |123bcd|
287 * |ghi{}l| |789012| |789hi#|
288 * |mnopqr| |......| |......|
289 * +------+ +------+ +------+
290 * Same a 5a. but with the right margin.
291 */
292