| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: addbytes.c,v 1.40 2013/10/16 19:59:29 roy Exp $ */ | | 1 | /* $NetBSD: addbytes.c,v 1.41 2013/11/09 11:16:59 blymn Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1987, 1993, 1994 | | 4 | * Copyright (c) 1987, 1993, 1994 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -24,132 +24,143 @@ | | | @@ -24,132 +24,143 @@ |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. | | 29 | * SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | #ifndef lint | | 33 | #ifndef lint |
34 | #if 0 | | 34 | #if 0 |
35 | static char sccsid[] = "@(#)addbytes.c 8.4 (Berkeley) 5/4/94"; | | 35 | static char sccsid[] = "@(#)addbytes.c 8.4 (Berkeley) 5/4/94"; |
36 | #else | | 36 | #else |
37 | __RCSID("$NetBSD: addbytes.c,v 1.40 2013/10/16 19:59:29 roy Exp $"); | | 37 | __RCSID("$NetBSD: addbytes.c,v 1.41 2013/11/09 11:16:59 blymn Exp $"); |
38 | #endif | | 38 | #endif |
39 | #endif /* not lint */ | | 39 | #endif /* not lint */ |
40 | | | 40 | |
41 | #include <stdlib.h> | | 41 | #include <stdlib.h> |
42 | #include <string.h> | | 42 | #include <string.h> |
43 | #include "curses.h" | | 43 | #include "curses.h" |
44 | #include "curses_private.h" | | 44 | #include "curses_private.h" |
45 | #ifdef DEBUG | | 45 | #ifdef DEBUG |
46 | #include <assert.h> | | 46 | #include <assert.h> |
47 | #endif | | 47 | #endif |
48 | | | 48 | |
49 | #define SYNCH_IN {y = win->cury; x = win->curx;} | | 49 | #define SYNCH_IN {y = win->cury; x = win->curx;} |
50 | #define SYNCH_OUT {win->cury = y; win->curx = x;} | | 50 | #define SYNCH_OUT {win->cury = y; win->curx = x;} |
51 | #define PSYNCH_IN {*y = win->cury; *x = win->curx;} | | 51 | #define PSYNCH_IN {*y = win->cury; *x = win->curx;} |
52 | #define PSYNCH_OUT {win->cury = *y; win->curx = *x;} | | 52 | #define PSYNCH_OUT {win->cury = *y; win->curx = *x;} |
53 | | | 53 | |
54 | #ifndef _CURSES_USE_MACROS | | 54 | #ifndef _CURSES_USE_MACROS |
55 | | | 55 | |
56 | /* | | 56 | /* |
57 | * addbytes -- | | 57 | * addbytes -- |
58 | * Add the character to the current position in stdscr. | | 58 | * Add the character to the current position in stdscr. |
59 | */ | | 59 | */ |
60 | int | | 60 | int |
61 | addbytes(const char *bytes, int count) | | 61 | addbytes(const char *bytes, int count) |
62 | { | | 62 | { |
63 | return __waddbytes(stdscr, bytes, count, 0); | | 63 | return _cursesi_waddbytes(stdscr, bytes, count, 0, 1); |
64 | } | | 64 | } |
65 | | | 65 | |
66 | /* | | 66 | /* |
67 | * waddbytes -- | | 67 | * waddbytes -- |
68 | * Add the character to the current position in the given window. | | 68 | * Add the character to the current position in the given window. |
69 | */ | | 69 | */ |
70 | int | | 70 | int |
71 | waddbytes(WINDOW *win, const char *bytes, int count) | | 71 | waddbytes(WINDOW *win, const char *bytes, int count) |
72 | { | | 72 | { |
73 | return __waddbytes(win, bytes, count, 0); | | 73 | return _cursesi_waddbytes(win, bytes, count, 0, 1); |
74 | } | | 74 | } |
75 | | | 75 | |
76 | /* | | 76 | /* |
77 | * mvaddbytes -- | | 77 | * mvaddbytes -- |
78 | * Add the characters to stdscr at the location given. | | 78 | * Add the characters to stdscr at the location given. |
79 | */ | | 79 | */ |
80 | int | | 80 | int |
81 | mvaddbytes(int y, int x, const char *bytes, int count) | | 81 | mvaddbytes(int y, int x, const char *bytes, int count) |
82 | { | | 82 | { |
83 | return mvwaddbytes(stdscr, y, x, bytes, count); | | 83 | return mvwaddbytes(stdscr, y, x, bytes, count); |
84 | } | | 84 | } |
85 | | | 85 | |
86 | /* | | 86 | /* |
87 | * mvwaddbytes -- | | 87 | * mvwaddbytes -- |
88 | * Add the characters to the given window at the location given. | | 88 | * Add the characters to the given window at the location given. |
89 | */ | | 89 | */ |
90 | int | | 90 | int |
91 | mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count) | | 91 | mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count) |
92 | { | | 92 | { |
93 | if (wmove(win, y, x) == ERR) | | 93 | if (wmove(win, y, x) == ERR) |
94 | return ERR; | | 94 | return ERR; |
95 | | | 95 | |
96 | return __waddbytes(win, bytes, count, 0); | | 96 | return _cursesi_waddbytes(win, bytes, count, 0, 1); |
97 | } | | 97 | } |
98 | | | 98 | |
99 | #endif | | 99 | #endif |
100 | | | 100 | |
| | | 101 | int |
| | | 102 | __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr) |
| | | 103 | { |
| | | 104 | return _cursesi_waddbytes(win, bytes, count, attr, 1); |
| | | 105 | } |
| | | 106 | |
101 | /* | | 107 | /* |
102 | * waddbytes -- | | 108 | * _cursesi_waddbytes -- |
103 | * Add the character to the current position in the given window. | | 109 | * Add the character to the current position in the given window. |
| | | 110 | * if char_interp is non-zero then character interpretation is done on |
| | | 111 | * the byte (i.e. \n to newline, \r to carriage return, \b to backspace |
| | | 112 | * and so on). |
104 | */ | | 113 | */ |
105 | int | | 114 | int |
106 | __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr) | | 115 | _cursesi_waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr, |
| | | 116 | int char_interp) |
107 | { | | 117 | { |
108 | int x, y, err; | | 118 | int ox, x, y, err; |
109 | __LINE *lp; | | 119 | __LINE *lp; |
110 | #ifdef HAVE_WCHAR | | 120 | #ifdef HAVE_WCHAR |
111 | int n; | | 121 | int n; |
112 | cchar_t cc; | | 122 | cchar_t cc; |
113 | wchar_t wc; | | 123 | wchar_t wc; |
114 | mbstate_t st; | | 124 | mbstate_t st; |
115 | #else | | 125 | #else |
116 | int c; | | 126 | int c; |
117 | #endif | | 127 | #endif |
118 | #ifdef DEBUG | | 128 | #ifdef DEBUG |
119 | int i; | | 129 | int i; |
120 | | | 130 | |
121 | for (i = 0; i < win->maxy; i++) { | | 131 | for (i = 0; i < win->maxy; i++) { |
122 | assert(win->alines[i]->sentinel == SENTINEL_VALUE); | | 132 | assert(win->alines[i]->sentinel == SENTINEL_VALUE); |
123 | } | | 133 | } |
124 | | | 134 | |
125 | __CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count); | | 135 | __CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count); |
126 | #endif | | 136 | #endif |
127 | | | 137 | |
128 | err = OK; | | 138 | err = OK; |
129 | SYNCH_IN; | | 139 | SYNCH_IN; |
130 | lp = win->alines[y]; | | 140 | lp = win->alines[y]; |
| | | 141 | ox = win->curx; |
131 | | | 142 | |
132 | #ifdef HAVE_WCHAR | | 143 | #ifdef HAVE_WCHAR |
133 | (void)memset(&st, 0, sizeof(st)); | | 144 | (void)memset(&st, 0, sizeof(st)); |
134 | #endif | | 145 | #endif |
135 | while (count > 0) { | | 146 | while (count > 0) { |
136 | #ifndef HAVE_WCHAR | | 147 | #ifndef HAVE_WCHAR |
137 | c = *bytes++; | | 148 | c = *bytes++; |
138 | #ifdef DEBUG | | 149 | #ifdef DEBUG |
139 | __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n", | | 150 | __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n", |
140 | c, attr, y, x); | | 151 | c, attr, y, x); |
141 | #endif | | 152 | #endif |
142 | err = _cursesi_addbyte(win, &lp, &y, &x, c, attr); | | 153 | err = _cursesi_addbyte(win, &lp, &y, &x, c, attr, char_interp); |
143 | count--; | | 154 | count--; |
144 | #else | | 155 | #else |
145 | /* | | 156 | /* |
146 | * For wide-character support only, try and convert the | | 157 | * For wide-character support only, try and convert the |
147 | * given string into a wide character - we do this because | | 158 | * given string into a wide character - we do this because |
148 | * this is how ncurses behaves (not that I think this is | | 159 | * this is how ncurses behaves (not that I think this is |
149 | * actually the correct thing to do but if we don't do it | | 160 | * actually the correct thing to do but if we don't do it |
150 | * a lot of things that rely on this behaviour will break | | 161 | * a lot of things that rely on this behaviour will break |
151 | * and we will be blamed). If the conversion succeeds | | 162 | * and we will be blamed). If the conversion succeeds |
152 | * then we eat the n characters used to make the wide char | | 163 | * then we eat the n characters used to make the wide char |
153 | * from the string. | | 164 | * from the string. |
154 | */ | | 165 | */ |
155 | n = (int)mbrtowc(&wc, bytes, (size_t)count, &st); | | 166 | n = (int)mbrtowc(&wc, bytes, (size_t)count, &st); |
| @@ -159,225 +170,233 @@ __waddbytes(WINDOW *win, const char *byt | | | @@ -159,225 +170,233 @@ __waddbytes(WINDOW *win, const char *byt |
159 | n = 1; | | 170 | n = 1; |
160 | (void)memset(&st, 0, sizeof(st)); | | 171 | (void)memset(&st, 0, sizeof(st)); |
161 | } else if (wc == 0) { | | 172 | } else if (wc == 0) { |
162 | break; | | 173 | break; |
163 | } | | 174 | } |
164 | #ifdef DEBUG | | 175 | #ifdef DEBUG |
165 | __CTRACE(__CTRACE_INPUT, | | 176 | __CTRACE(__CTRACE_INPUT, |
166 | "ADDBYTES WIDE(0x%x [%s], %x) at (%d, %d), ate %d bytes\n", | | 177 | "ADDBYTES WIDE(0x%x [%s], %x) at (%d, %d), ate %d bytes\n", |
167 | (unsigned) wc, unctrl((unsigned) wc), attr, y, x, n); | | 178 | (unsigned) wc, unctrl((unsigned) wc), attr, y, x, n); |
168 | #endif | | 179 | #endif |
169 | cc.vals[0] = wc; | | 180 | cc.vals[0] = wc; |
170 | cc.elements = 1; | | 181 | cc.elements = 1; |
171 | cc.attributes = attr; | | 182 | cc.attributes = attr; |
172 | err = _cursesi_addwchar(win, &lp, &y, &x, &cc); | | 183 | err = _cursesi_addwchar(win, &lp, &y, &x, &cc, char_interp); |
173 | bytes += n; | | 184 | bytes += n; |
174 | count -= n; | | 185 | count -= n; |
175 | #endif | | 186 | #endif |
176 | } | | 187 | } |
177 | | | 188 | |
178 | SYNCH_OUT; | | 189 | SYNCH_OUT; |
179 | | | 190 | |
180 | #ifdef DEBUG | | 191 | #ifdef DEBUG |
181 | for (i = 0; i < win->maxy; i++) { | | 192 | for (i = 0; i < win->maxy; i++) { |
182 | assert(win->alines[i]->sentinel == SENTINEL_VALUE); | | 193 | assert(win->alines[i]->sentinel == SENTINEL_VALUE); |
183 | } | | 194 | } |
184 | #endif | | 195 | #endif |
185 | | | 196 | |
186 | return (err); | | 197 | return (err); |
187 | } | | 198 | } |
188 | | | 199 | |
189 | /* | | 200 | /* |
190 | * _cursesi_addbyte - | | 201 | * _cursesi_addbyte - |
191 | * Internal function to add a byte and update the row and column | | 202 | * Internal function to add a byte and update the row and column |
192 | * positions as appropriate. This function is only used in the narrow | | 203 | * positions as appropriate. This function is only used in the narrow |
193 | * character version of curses. | | 204 | * character version of curses. If update_cursor is non-zero then character |
| | | 205 | * interpretation. |
194 | */ | | 206 | */ |
195 | int | | 207 | int |
196 | _cursesi_addbyte(WINDOW *win, __LINE **lp, int *y, int *x, int c, | | 208 | _cursesi_addbyte(WINDOW *win, __LINE **lp, int *y, int *x, int c, |
197 | attr_t attr) | | 209 | attr_t attr, int char_interp) |
198 | { | | 210 | { |
199 | static char blanks[] = " "; | | 211 | static char blank[] = " "; |
200 | int newx; | | | |
201 | attr_t attributes; | | | |
202 | int tabsize; | | 212 | int tabsize; |
| | | 213 | int newx, i; |
| | | 214 | attr_t attributes; |
203 | | | 215 | |
204 | switch (c) { | | 216 | if (char_interp) { |
205 | case '\t': | | 217 | switch (c) { |
206 | tabsize = win->screen->TABSIZE; | | 218 | case '\t': |
207 | PSYNCH_OUT; | | 219 | tabsize = win->screen->TABSIZE; |
208 | if (waddbytes(win, blanks, tabsize - (*x % tabsize)) == ERR) | | 220 | PSYNCH_OUT; |
209 | return (ERR); | | 221 | for (i = 0; i < (tabsize - (*x % tabsize)); i++) { |
210 | PSYNCH_IN; | | 222 | if (waddbytes(win, blank, 1) == ERR) |
211 | break; | | 223 | return (ERR); |
| | | 224 | } |
| | | 225 | PSYNCH_IN; |
| | | 226 | return (OK); |
| | | 227 | |
| | | 228 | case '\n': |
| | | 229 | PSYNCH_OUT; |
| | | 230 | wclrtoeol(win); |
| | | 231 | PSYNCH_IN; |
| | | 232 | (*lp)->flags |= __ISPASTEOL; |
| | | 233 | break; |
| | | 234 | |
| | | 235 | case '\r': |
| | | 236 | *x = 0; |
| | | 237 | win->curx = *x; |
| | | 238 | return (OK); |
| | | 239 | |
| | | 240 | case '\b': |
| | | 241 | if (--(*x) < 0) |
| | | 242 | *x = 0; |
| | | 243 | win->curx = *x; |
| | | 244 | return (OK); |
| | | 245 | } |
| | | 246 | } |
212 | | | 247 | |
213 | default: | | | |
214 | #ifdef DEBUG | | 248 | #ifdef DEBUG |
215 | __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", | | 249 | __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", win, *y, *x); |
216 | win, *y, *x); | | | |
217 | #endif | | 250 | #endif |
218 | | | 251 | |
219 | if ((*lp)->flags & __ISPASTEOL) { | | 252 | if (char_interp && ((*lp)->flags & __ISPASTEOL)) { |
220 | new_line: | | 253 | *x = 0; |
221 | *x = 0; | | 254 | (*lp)->flags &= ~__ISPASTEOL; |
222 | (*lp)->flags &= ~__ISPASTEOL; | | 255 | if (*y == win->scr_b) { |
223 | if (*y == win->scr_b) { | | | |
224 | #ifdef DEBUG | | 256 | #ifdef DEBUG |
225 | __CTRACE(__CTRACE_INPUT, | | 257 | __CTRACE(__CTRACE_INPUT, |
226 | "ADDBYTES - on bottom " | | 258 | "ADDBYTES - on bottom " |
227 | "of scrolling region\n"); | | 259 | "of scrolling region\n"); |
228 | #endif | | 260 | #endif |
229 | if (!(win->flags & __SCROLLOK)) | | 261 | if (!(win->flags & __SCROLLOK)) |
230 | return ERR; | | 262 | return ERR; |
231 | PSYNCH_OUT; | | 263 | PSYNCH_OUT; |
232 | scroll(win); | | 264 | scroll(win); |
233 | PSYNCH_IN; | | 265 | PSYNCH_IN; |
234 | } else { | | 266 | } else { |
235 | (*y)++; | | 267 | (*y)++; |
236 | } | | | |
237 | *lp = win->alines[*y]; | | | |
238 | if (c == '\n') | | | |
239 | break; | | | |
240 | } | | 268 | } |
| | | 269 | *lp = win->alines[*y]; |
| | | 270 | if (c == '\n') |
| | | 271 | return (OK); |
| | | 272 | } |
241 | | | 273 | |
242 | attributes = (win->wattr | attr) & | | | |
243 | (__ATTRIBUTES & ~__COLOR); | | | |
244 | if (attr & __COLOR) | | | |
245 | attributes |= attr & __COLOR; | | | |
246 | else if (win->wattr & __COLOR) | | | |
247 | attributes |= win->wattr & __COLOR; | | | |
248 | #ifdef DEBUG | | 274 | #ifdef DEBUG |
249 | __CTRACE(__CTRACE_INPUT, | | 275 | __CTRACE(__CTRACE_INPUT, |
250 | "ADDBYTES: 1: y = %d, x = %d, firstch = %d, " | | 276 | "ADDBYTES: 1: y = %d, x = %d, firstch = %d, lastch = %d\n", |
251 | "lastch = %d\n", | | 277 | *y, *x, *win->alines[*y]->firstchp, |
252 | *y, *x, *win->alines[*y]->firstchp, | | 278 | *win->alines[*y]->lastchp); |
253 | *win->alines[*y]->lastchp); | | | |
254 | #endif | | 279 | #endif |
255 | /* | | | |
256 | * Always update the change pointers. Otherwise, | | | |
257 | * we could end up not displaying 'blank' characters | | | |
258 | * when overlapping windows are displayed. | | | |
259 | */ | | | |
260 | newx = *x + win->ch_off; | | | |
261 | (*lp)->flags |= __ISDIRTY; | | | |
262 | /* | | | |
263 | * firstchp/lastchp are shared between | | | |
264 | * parent window and sub-window. | | | |
265 | */ | | | |
266 | if (newx < *(*lp)->firstchp) | | | |
267 | *(*lp)->firstchp = newx; | | | |
268 | if (newx > *(*lp)->lastchp) | | | |
269 | *(*lp)->lastchp = newx; | | | |
270 | #ifdef DEBUG | | | |
271 | __CTRACE(__CTRACE_INPUT, | | | |
272 | "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", | | | |
273 | *(*lp)->firstchp, *(*lp)->lastchp, | | | |
274 | *(*lp)->firstchp - win->ch_off, | | | |
275 | *(*lp)->lastchp - win->ch_off); | | | |
276 | #endif | | | |
277 | if (win->bch != ' ' && c == ' ') | | | |
278 | (*lp)->line[*x].ch = win->bch; | | | |
279 | else | | | |
280 | (*lp)->line[*x].ch = c; | | | |
281 | | | | |
282 | if (attributes & __COLOR) | | | |
283 | (*lp)->line[*x].attr = | | | |
284 | attributes | (win->battr & ~__COLOR); | | | |
285 | else | | | |
286 | (*lp)->line[*x].attr = attributes | win->battr; | | | |
287 | | | 280 | |
288 | if (*x == win->maxx - 1) | | 281 | attributes = (win->wattr | attr) & (__ATTRIBUTES & ~__COLOR); |
289 | (*lp)->flags |= __ISPASTEOL; | | 282 | if (attr & __COLOR) |
290 | else | | 283 | attributes |= attr & __COLOR; |
291 | (*x)++; | | 284 | else if (win->wattr & __COLOR) |
292 | #ifdef DEBUG | | 285 | attributes |= win->wattr & __COLOR; |
293 | __CTRACE(__CTRACE_INPUT, | | | |
294 | "ADDBYTES: 2: y = %d, x = %d, firstch = %d, " | | | |
295 | "lastch = %d\n", | | | |
296 | *y, *x, *win->alines[*y]->firstchp, | | | |
297 | *win->alines[*y]->lastchp); | | | |
298 | #endif | | | |
299 | break; | | | |
300 | case '\n': | | | |
301 | PSYNCH_OUT; | | | |
302 | wclrtoeol(win); | | | |
303 | PSYNCH_IN; | | | |
304 | goto new_line; | | | |
305 | case '\r': | | | |
306 | *x = 0; | | | |
307 | break; | | | |
308 | case '\b': | | | |
309 | if (--(*x) < 0) | | | |
310 | *x = 0; | | | |
311 | break; | | | |
312 | } | | | |
313 | | | 286 | |
| | | 287 | /* |
| | | 288 | * Always update the change pointers. Otherwise, |
| | | 289 | * we could end up not displaying 'blank' characters |
| | | 290 | * when overlapping windows are displayed. |
| | | 291 | */ |
| | | 292 | newx = *x + win->ch_off; |
| | | 293 | (*lp)->flags |= __ISDIRTY; |
| | | 294 | /* |
| | | 295 | * firstchp/lastchp are shared between |
| | | 296 | * parent window and sub-window. |
| | | 297 | */ |
| | | 298 | if (newx < *(*lp)->firstchp) |
| | | 299 | *(*lp)->firstchp = newx; |
| | | 300 | if (newx > *(*lp)->lastchp) |
| | | 301 | *(*lp)->lastchp = newx; |
| | | 302 | #ifdef DEBUG |
| | | 303 | __CTRACE(__CTRACE_INPUT, "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", |
| | | 304 | *(*lp)->firstchp, *(*lp)->lastchp, |
| | | 305 | *(*lp)->firstchp - win->ch_off, |
| | | 306 | *(*lp)->lastchp - win->ch_off); |
| | | 307 | #endif |
| | | 308 | if (win->bch != ' ' && c == ' ') |
| | | 309 | (*lp)->line[*x].ch = win->bch; |
| | | 310 | else |
| | | 311 | (*lp)->line[*x].ch = c; |
| | | 312 | |
| | | 313 | if (attributes & __COLOR) |
| | | 314 | (*lp)->line[*x].attr = |
| | | 315 | attributes | (win->battr & ~__COLOR); |
| | | 316 | else |
| | | 317 | (*lp)->line[*x].attr = attributes | win->battr; |
| | | 318 | |
| | | 319 | if (*x == win->maxx - 1) |
| | | 320 | (*lp)->flags |= __ISPASTEOL; |
| | | 321 | else |
| | | 322 | (*x)++; |
| | | 323 | |
| | | 324 | #ifdef DEBUG |
| | | 325 | __CTRACE(__CTRACE_INPUT, |
| | | 326 | "ADDBYTES: 2: y = %d, x = %d, firstch = %d, lastch = %d\n", |
| | | 327 | *y, *x, *win->alines[*y]->firstchp, |
| | | 328 | *win->alines[*y]->lastchp); |
| | | 329 | #endif |
314 | return (OK); | | 330 | return (OK); |
315 | } | | 331 | } |
316 | | | 332 | |
317 | /* | | 333 | /* |
318 | * _cursesi_addwchar - | | 334 | * _cursesi_addwchar - |
319 | * Internal function to add a wide character and update the row | | 335 | * Internal function to add a wide character and update the row |
320 | * and column positions. | | 336 | * and column positions. |
321 | */ | | 337 | */ |
322 | int | | 338 | int |
323 | _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x, | | 339 | _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x, |
324 | const cchar_t *wch) | | 340 | const cchar_t *wch, int char_interp) |
325 | { | | 341 | { |
326 | #ifndef HAVE_WCHAR | | 342 | #ifndef HAVE_WCHAR |
327 | return (ERR); | | 343 | return (ERR); |
328 | #else | | 344 | #else |
329 | int sx = 0, ex = 0, cw = 0, i = 0, newx = 0, tabsize; | | 345 | int sx = 0, ex = 0, cw = 0, i = 0, newx = 0, tabsize; |
330 | __LDATA *lp = &win->alines[*y]->line[*x], *tp = NULL; | | 346 | __LDATA *lp = &win->alines[*y]->line[*x], *tp = NULL; |
331 | nschar_t *np = NULL; | | 347 | nschar_t *np = NULL; |
332 | cchar_t cc; | | 348 | cchar_t cc; |
333 | attr_t attributes; | | 349 | attr_t attributes; |
334 | | | 350 | |
335 | /* special characters handling */ | | 351 | if (char_interp) { |
336 | switch (wch->vals[0]) { | | 352 | /* special characters handling */ |
337 | case L'\b': | | 353 | switch (wch->vals[0]) { |
338 | if (--*x < 0) | | 354 | case L'\b': |
| | | 355 | if (--*x < 0) |
| | | 356 | *x = 0; |
| | | 357 | win->curx = *x; |
| | | 358 | return OK; |
| | | 359 | case L'\r': |
339 | *x = 0; | | 360 | *x = 0; |
340 | win->curx = *x; | | 361 | win->curx = *x; |
341 | return OK; | | 362 | return OK; |
342 | case L'\r': | | 363 | case L'\n': |
343 | *x = 0; | | 364 | wclrtoeol(win); |
344 | return OK; | | | |
345 | case L'\n': | | | |
346 | wclrtoeol(win); | | | |
347 | PSYNCH_IN; | | | |
348 | *x = 0; | | | |
349 | (*lnp)->flags &= ~__ISPASTEOL; | | | |
350 | if (*y == win->scr_b) { | | | |
351 | if (!(win->flags & __SCROLLOK)) | | | |
352 | return ERR; | | | |
353 | PSYNCH_OUT; | | | |
354 | scroll(win); | | | |
355 | PSYNCH_IN; | | 365 | PSYNCH_IN; |
356 | } else { | | 366 | *x = 0; |
357 | (*y)++; | | 367 | (*lnp)->flags &= ~__ISPASTEOL; |
358 | } | | 368 | if (*y == win->scr_b) { |
359 | PSYNCH_OUT; | | 369 | if (!(win->flags & __SCROLLOK)) |
360 | return OK; | | 370 | return ERR; |
361 | case L'\t': | | 371 | PSYNCH_OUT; |
362 | cc.vals[0] = L' '; | | 372 | scroll(win); |
363 | cc.elements = 1; | | 373 | PSYNCH_IN; |
364 | cc.attributes = win->wattr; | | 374 | } else { |
365 | tabsize = win->screen->TABSIZE; | | 375 | (*y)++; |
366 | for (i = 0; i < tabsize - (*x % tabsize); i++) { | | 376 | } |
367 | if (wadd_wch(win, &cc) == ERR) | | 377 | PSYNCH_OUT; |
368 | return ERR; | | 378 | return OK; |
| | | 379 | case L'\t': |
| | | 380 | cc.vals[0] = L' '; |
| | | 381 | cc.elements = 1; |
| | | 382 | cc.attributes = win->wattr; |
| | | 383 | tabsize = win->screen->TABSIZE; |
| | | 384 | for (i = 0; i < tabsize - (*x % tabsize); i++) { |
| | | 385 | if (wadd_wch(win, &cc) == ERR) |
| | | 386 | return ERR; |
| | | 387 | } |
| | | 388 | return OK; |
369 | } | | 389 | } |
370 | return OK; | | | |
371 | } | | 390 | } |
372 | | | 391 | |
373 | /* check for non-spacing character */ | | 392 | /* check for non-spacing character */ |
374 | if (!wcwidth(wch->vals[0])) { | | 393 | if (!wcwidth(wch->vals[0])) { |
375 | #ifdef DEBUG | | 394 | #ifdef DEBUG |
376 | __CTRACE(__CTRACE_INPUT, | | 395 | __CTRACE(__CTRACE_INPUT, |
377 | "_cursesi_addwchar: char '%c' is non-spacing\n", | | 396 | "_cursesi_addwchar: char '%c' is non-spacing\n", |
378 | wch->vals[0]); | | 397 | wch->vals[0]); |
379 | #endif /* DEBUG */ | | 398 | #endif /* DEBUG */ |
380 | cw = WCOL(*lp); | | 399 | cw = WCOL(*lp); |
381 | if (cw < 0) { | | 400 | if (cw < 0) { |
382 | lp += cw; | | 401 | lp += cw; |
383 | *x += cw; | | 402 | *x += cw; |
| @@ -389,27 +408,27 @@ _cursesi_addwchar(WINDOW *win, __LINE ** | | | @@ -389,27 +408,27 @@ _cursesi_addwchar(WINDOW *win, __LINE ** |
389 | np->next = lp->nsp; | | 408 | np->next = lp->nsp; |
390 | lp->nsp = np; | | 409 | lp->nsp = np; |
391 | } | | 410 | } |
392 | (*lnp)->flags |= __ISDIRTY; | | 411 | (*lnp)->flags |= __ISDIRTY; |
393 | newx = *x + win->ch_off; | | 412 | newx = *x + win->ch_off; |
394 | if (newx < *(*lnp)->firstchp) | | 413 | if (newx < *(*lnp)->firstchp) |
395 | *(*lnp)->firstchp = newx; | | 414 | *(*lnp)->firstchp = newx; |
396 | if (newx > *(*lnp)->lastchp) | | 415 | if (newx > *(*lnp)->lastchp) |
397 | *(*lnp)->lastchp = newx; | | 416 | *(*lnp)->lastchp = newx; |
398 | __touchline(win, *y, *x, *x); | | 417 | __touchline(win, *y, *x, *x); |
399 | return OK; | | 418 | return OK; |
400 | } | | 419 | } |
401 | /* check for new line first */ | | 420 | /* check for new line first */ |
402 | if ((*lnp)->flags & __ISPASTEOL) { | | 421 | if (char_interp && ((*lnp)->flags & __ISPASTEOL)) { |
403 | *x = 0; | | 422 | *x = 0; |
404 | (*lnp)->flags &= ~__ISPASTEOL; | | 423 | (*lnp)->flags &= ~__ISPASTEOL; |
405 | if (*y == win->scr_b) { | | 424 | if (*y == win->scr_b) { |
406 | if (!(win->flags & __SCROLLOK)) | | 425 | if (!(win->flags & __SCROLLOK)) |
407 | return ERR; | | 426 | return ERR; |
408 | PSYNCH_OUT; | | 427 | PSYNCH_OUT; |
409 | scroll(win); | | 428 | scroll(win); |
410 | PSYNCH_IN; | | 429 | PSYNCH_IN; |
411 | } else { | | 430 | } else { |
412 | (*y)++; | | 431 | (*y)++; |
413 | } | | 432 | } |
414 | (*lnp) = win->alines[*y]; | | 433 | (*lnp) = win->alines[*y]; |
415 | lp = &win->alines[*y]->line[*x]; | | 434 | lp = &win->alines[*y]->line[*x]; |
| @@ -434,26 +453,27 @@ _cursesi_addwchar(WINDOW *win, __LINE ** | | | @@ -434,26 +453,27 @@ _cursesi_addwchar(WINDOW *win, __LINE ** |
434 | SET_WCOL(*tp, 1); | | 453 | SET_WCOL(*tp, 1); |
435 | } | | 454 | } |
436 | sx = *x + cw; | | 455 | sx = *x + cw; |
437 | (*lnp)->flags |= __ISDIRTY; | | 456 | (*lnp)->flags |= __ISDIRTY; |
438 | newx = sx + win->ch_off; | | 457 | newx = sx + win->ch_off; |
439 | if (newx < *(*lnp)->firstchp) | | 458 | if (newx < *(*lnp)->firstchp) |
440 | *(*lnp)->firstchp = newx; | | 459 | *(*lnp)->firstchp = newx; |
441 | } | | 460 | } |
442 | | | 461 | |
443 | /* check for enough space before the end of line */ | | 462 | /* check for enough space before the end of line */ |
444 | cw = wcwidth(wch->vals[0]); | | 463 | cw = wcwidth(wch->vals[0]); |
445 | if (cw < 0) | | 464 | if (cw < 0) |
446 | cw = 1; | | 465 | cw = 1; |
| | | 466 | |
447 | if (cw > win->maxx - *x) { | | 467 | if (cw > win->maxx - *x) { |
448 | #ifdef DEBUG | | 468 | #ifdef DEBUG |
449 | __CTRACE(__CTRACE_INPUT, | | 469 | __CTRACE(__CTRACE_INPUT, |
450 | "_cursesi_addwchar: clear EOL (%d,%d)\n", | | 470 | "_cursesi_addwchar: clear EOL (%d,%d)\n", |
451 | *y, *x); | | 471 | *y, *x); |
452 | #endif /* DEBUG */ | | 472 | #endif /* DEBUG */ |
453 | (*lnp)->flags |= __ISDIRTY; | | 473 | (*lnp)->flags |= __ISDIRTY; |
454 | newx = *x + win->ch_off; | | 474 | newx = *x + win->ch_off; |
455 | if (newx < *(*lnp)->firstchp) | | 475 | if (newx < *(*lnp)->firstchp) |
456 | *(*lnp)->firstchp = newx; | | 476 | *(*lnp)->firstchp = newx; |
457 | for (tp = lp; *x < win->maxx; tp++, (*x)++) { | | 477 | for (tp = lp; *x < win->maxx; tp++, (*x)++) { |
458 | tp->ch = (wchar_t) btowc((int) win->bch); | | 478 | tp->ch = (wchar_t) btowc((int) win->bch); |
459 | if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) | | 479 | if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) |
| @@ -536,46 +556,47 @@ _cursesi_addwchar(WINDOW *win, __LINE ** | | | @@ -536,46 +556,47 @@ _cursesi_addwchar(WINDOW *win, __LINE ** |
536 | __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: add rest columns (%d:%d)\n", | | 556 | __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: add rest columns (%d:%d)\n", |
537 | sx + 1, sx + cw - 1); | | 557 | sx + 1, sx + cw - 1); |
538 | #endif /* DEBUG */ | | 558 | #endif /* DEBUG */ |
539 | for (tp = lp + 1, *x = sx + 1; *x - sx <= cw - 1; tp++, (*x)++) { | | 559 | for (tp = lp + 1, *x = sx + 1; *x - sx <= cw - 1; tp++, (*x)++) { |
540 | if (tp->nsp) { | | 560 | if (tp->nsp) { |
541 | __cursesi_free_nsp(tp->nsp); | | 561 | __cursesi_free_nsp(tp->nsp); |
542 | tp->nsp = NULL; | | 562 | tp->nsp = NULL; |
543 | } | | 563 | } |
544 | tp->ch = wch->vals[0]; | | 564 | tp->ch = wch->vals[0]; |
545 | tp->attr = lp->attr & WA_ATTRIBUTES; | | 565 | tp->attr = lp->attr & WA_ATTRIBUTES; |
546 | /* Mark as "continuation" cell */ | | 566 | /* Mark as "continuation" cell */ |
547 | tp->attr |= __WCWIDTH; | | 567 | tp->attr |= __WCWIDTH; |
548 | } | | 568 | } |
| | | 569 | |
549 | if (*x == win->maxx) { | | 570 | if (*x == win->maxx) { |
550 | (*lnp)->flags |= __ISPASTEOL; | | 571 | (*lnp)->flags |= __ISPASTEOL; |
551 | newx = win->maxx - 1 + win->ch_off; | | 572 | newx = win->maxx - 1 + win->ch_off; |
552 | if (newx > *(*lnp)->lastchp) | | 573 | if (newx > *(*lnp)->lastchp) |
553 | *(*lnp)->lastchp = newx; | | 574 | *(*lnp)->lastchp = newx; |
554 | __touchline(win, *y, sx, (int) win->maxx - 1); | | 575 | __touchline(win, *y, sx, (int) win->maxx - 1); |
555 | win->curx = sx; | | 576 | win->curx = sx; |
556 | } else { | | 577 | } else { |
557 | win->curx = *x; | | 578 | win->curx = *x; |
558 | | | 579 | |
559 | /* clear the remining of the current characer */ | | 580 | /* clear the remining of the current characer */ |
560 | if (*x && *x < win->maxx) { | | 581 | if (*x && *x < win->maxx) { |
561 | ex = sx + cw; | | 582 | ex = sx + cw; |
562 | tp = &win->alines[*y]->line[ex]; | | 583 | tp = &win->alines[*y]->line[ex]; |
563 | while (ex < win->maxx && WCOL(*tp) < 0) { | | 584 | while (ex < win->maxx && WCOL(*tp) < 0) { |
564 | #ifdef DEBUG | | 585 | #ifdef DEBUG |
565 | __CTRACE(__CTRACE_INPUT, | | 586 | __CTRACE(__CTRACE_INPUT, |
566 | "_cursesi_addwchar: clear " | | 587 | "_cursesi_addwchar: clear " |
567 | "remaining of current char (%d,%d)nn", | | 588 | "remaining of current char (%d,%d)nn", |
568 | *y, ex); | | 589 | *y, ex); |
569 | #endif /* DEBUG */ | | 590 | #endif /* DEBUG */ |
570 | tp->ch = (wchar_t) btowc((int) win->bch); | | 591 | tp->ch = (wchar_t) btowc((int) win->bch); |
571 | if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) | | 592 | if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) |
572 | return ERR; | | 593 | return ERR; |
573 | tp->attr = win->battr; | | 594 | tp->attr = win->battr; |
574 | SET_WCOL(*tp, 1); | | 595 | SET_WCOL(*tp, 1); |
575 | tp++, ex++; | | 596 | tp++, ex++; |
576 | } | | 597 | } |
577 | newx = ex - 1 + win->ch_off; | | 598 | newx = ex - 1 + win->ch_off; |
578 | if (newx > *(*lnp)->lastchp) | | 599 | if (newx > *(*lnp)->lastchp) |
579 | *(*lnp)->lastchp = newx; | | 600 | *(*lnp)->lastchp = newx; |
580 | __touchline(win, *y, sx, ex - 1); | | 601 | __touchline(win, *y, sx, ex - 1); |
581 | } | | 602 | } |