1*84d9c625SLionel Sambuc /* $NetBSD: addbytes.c,v 1.42 2013/11/10 03:14:16 christos Exp $ */
251ffecc1SBen Gras
351ffecc1SBen Gras /*
451ffecc1SBen Gras * Copyright (c) 1987, 1993, 1994
551ffecc1SBen Gras * The Regents of the University of California. All rights reserved.
651ffecc1SBen Gras *
751ffecc1SBen Gras * Redistribution and use in source and binary forms, with or without
851ffecc1SBen Gras * modification, are permitted provided that the following conditions
951ffecc1SBen Gras * are met:
1051ffecc1SBen Gras * 1. Redistributions of source code must retain the above copyright
1151ffecc1SBen Gras * notice, this list of conditions and the following disclaimer.
1251ffecc1SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
1351ffecc1SBen Gras * notice, this list of conditions and the following disclaimer in the
1451ffecc1SBen Gras * documentation and/or other materials provided with the distribution.
1551ffecc1SBen Gras * 3. Neither the name of the University nor the names of its contributors
1651ffecc1SBen Gras * may be used to endorse or promote products derived from this software
1751ffecc1SBen Gras * without specific prior written permission.
1851ffecc1SBen Gras *
1951ffecc1SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2051ffecc1SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2151ffecc1SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2251ffecc1SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2351ffecc1SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2451ffecc1SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2551ffecc1SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2651ffecc1SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2751ffecc1SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2851ffecc1SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2951ffecc1SBen Gras * SUCH DAMAGE.
3051ffecc1SBen Gras */
3151ffecc1SBen Gras
3251ffecc1SBen Gras #include <sys/cdefs.h>
3351ffecc1SBen Gras #ifndef lint
3451ffecc1SBen Gras #if 0
3551ffecc1SBen Gras static char sccsid[] = "@(#)addbytes.c 8.4 (Berkeley) 5/4/94";
3651ffecc1SBen Gras #else
37*84d9c625SLionel Sambuc __RCSID("$NetBSD: addbytes.c,v 1.42 2013/11/10 03:14:16 christos Exp $");
3851ffecc1SBen Gras #endif
3951ffecc1SBen Gras #endif /* not lint */
4051ffecc1SBen Gras
4151ffecc1SBen Gras #include <stdlib.h>
4251ffecc1SBen Gras #include <string.h>
4351ffecc1SBen Gras #include "curses.h"
4451ffecc1SBen Gras #include "curses_private.h"
4551ffecc1SBen Gras #ifdef DEBUG
4651ffecc1SBen Gras #include <assert.h>
4751ffecc1SBen Gras #endif
4851ffecc1SBen Gras
4951ffecc1SBen Gras #define SYNCH_IN {y = win->cury; x = win->curx;}
5051ffecc1SBen Gras #define SYNCH_OUT {win->cury = y; win->curx = x;}
5151ffecc1SBen Gras #define PSYNCH_IN {*y = win->cury; *x = win->curx;}
5251ffecc1SBen Gras #define PSYNCH_OUT {win->cury = *y; win->curx = *x;}
5351ffecc1SBen Gras
5451ffecc1SBen Gras #ifndef _CURSES_USE_MACROS
5551ffecc1SBen Gras
5651ffecc1SBen Gras /*
5751ffecc1SBen Gras * addbytes --
5851ffecc1SBen Gras * Add the character to the current position in stdscr.
5951ffecc1SBen Gras */
6051ffecc1SBen Gras int
addbytes(const char * bytes,int count)6151ffecc1SBen Gras addbytes(const char *bytes, int count)
6251ffecc1SBen Gras {
63*84d9c625SLionel Sambuc return _cursesi_waddbytes(stdscr, bytes, count, 0, 1);
6451ffecc1SBen Gras }
6551ffecc1SBen Gras
6651ffecc1SBen Gras /*
6751ffecc1SBen Gras * waddbytes --
6851ffecc1SBen Gras * Add the character to the current position in the given window.
6951ffecc1SBen Gras */
7051ffecc1SBen Gras int
waddbytes(WINDOW * win,const char * bytes,int count)7151ffecc1SBen Gras waddbytes(WINDOW *win, const char *bytes, int count)
7251ffecc1SBen Gras {
73*84d9c625SLionel Sambuc return _cursesi_waddbytes(win, bytes, count, 0, 1);
7451ffecc1SBen Gras }
7551ffecc1SBen Gras
7651ffecc1SBen Gras /*
7751ffecc1SBen Gras * mvaddbytes --
7851ffecc1SBen Gras * Add the characters to stdscr at the location given.
7951ffecc1SBen Gras */
8051ffecc1SBen Gras int
mvaddbytes(int y,int x,const char * bytes,int count)8151ffecc1SBen Gras mvaddbytes(int y, int x, const char *bytes, int count)
8251ffecc1SBen Gras {
8351ffecc1SBen Gras return mvwaddbytes(stdscr, y, x, bytes, count);
8451ffecc1SBen Gras }
8551ffecc1SBen Gras
8651ffecc1SBen Gras /*
8751ffecc1SBen Gras * mvwaddbytes --
8851ffecc1SBen Gras * Add the characters to the given window at the location given.
8951ffecc1SBen Gras */
9051ffecc1SBen Gras int
mvwaddbytes(WINDOW * win,int y,int x,const char * bytes,int count)9151ffecc1SBen Gras mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count)
9251ffecc1SBen Gras {
9351ffecc1SBen Gras if (wmove(win, y, x) == ERR)
9451ffecc1SBen Gras return ERR;
9551ffecc1SBen Gras
96*84d9c625SLionel Sambuc return _cursesi_waddbytes(win, bytes, count, 0, 1);
9751ffecc1SBen Gras }
9851ffecc1SBen Gras
9951ffecc1SBen Gras #endif
10051ffecc1SBen Gras
10151ffecc1SBen Gras int
__waddbytes(WINDOW * win,const char * bytes,int count,attr_t attr)10251ffecc1SBen Gras __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr)
10351ffecc1SBen Gras {
104*84d9c625SLionel Sambuc return _cursesi_waddbytes(win, bytes, count, attr, 1);
105*84d9c625SLionel Sambuc }
106*84d9c625SLionel Sambuc
107*84d9c625SLionel Sambuc /*
108*84d9c625SLionel Sambuc * _cursesi_waddbytes --
109*84d9c625SLionel Sambuc * Add the character to the current position in the given window.
110*84d9c625SLionel Sambuc * if char_interp is non-zero then character interpretation is done on
111*84d9c625SLionel Sambuc * the byte (i.e. \n to newline, \r to carriage return, \b to backspace
112*84d9c625SLionel Sambuc * and so on).
113*84d9c625SLionel Sambuc */
114*84d9c625SLionel Sambuc int
_cursesi_waddbytes(WINDOW * win,const char * bytes,int count,attr_t attr,int char_interp)115*84d9c625SLionel Sambuc _cursesi_waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr,
116*84d9c625SLionel Sambuc int char_interp)
117*84d9c625SLionel Sambuc {
11851ffecc1SBen Gras int x, y, err;
11951ffecc1SBen Gras __LINE *lp;
12051ffecc1SBen Gras #ifdef HAVE_WCHAR
12151ffecc1SBen Gras int n;
12251ffecc1SBen Gras cchar_t cc;
12351ffecc1SBen Gras wchar_t wc;
12451ffecc1SBen Gras mbstate_t st;
12551ffecc1SBen Gras #else
12651ffecc1SBen Gras int c;
12751ffecc1SBen Gras #endif
12851ffecc1SBen Gras #ifdef DEBUG
12951ffecc1SBen Gras int i;
13051ffecc1SBen Gras
13151ffecc1SBen Gras for (i = 0; i < win->maxy; i++) {
13251ffecc1SBen Gras assert(win->alines[i]->sentinel == SENTINEL_VALUE);
13351ffecc1SBen Gras }
13451ffecc1SBen Gras
13551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count);
13651ffecc1SBen Gras #endif
13751ffecc1SBen Gras
13851ffecc1SBen Gras err = OK;
13951ffecc1SBen Gras SYNCH_IN;
14051ffecc1SBen Gras lp = win->alines[y];
14151ffecc1SBen Gras
14251ffecc1SBen Gras #ifdef HAVE_WCHAR
14351ffecc1SBen Gras (void)memset(&st, 0, sizeof(st));
14451ffecc1SBen Gras #endif
14551ffecc1SBen Gras while (count > 0) {
14651ffecc1SBen Gras #ifndef HAVE_WCHAR
14751ffecc1SBen Gras c = *bytes++;
14851ffecc1SBen Gras #ifdef DEBUG
14951ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n",
15051ffecc1SBen Gras c, attr, y, x);
15151ffecc1SBen Gras #endif
152*84d9c625SLionel Sambuc err = _cursesi_addbyte(win, &lp, &y, &x, c, attr, char_interp);
15351ffecc1SBen Gras count--;
15451ffecc1SBen Gras #else
15551ffecc1SBen Gras /*
15651ffecc1SBen Gras * For wide-character support only, try and convert the
15751ffecc1SBen Gras * given string into a wide character - we do this because
15851ffecc1SBen Gras * this is how ncurses behaves (not that I think this is
15951ffecc1SBen Gras * actually the correct thing to do but if we don't do it
16051ffecc1SBen Gras * a lot of things that rely on this behaviour will break
16151ffecc1SBen Gras * and we will be blamed). If the conversion succeeds
16251ffecc1SBen Gras * then we eat the n characters used to make the wide char
16351ffecc1SBen Gras * from the string.
16451ffecc1SBen Gras */
16551ffecc1SBen Gras n = (int)mbrtowc(&wc, bytes, (size_t)count, &st);
16651ffecc1SBen Gras if (n < 0) {
16751ffecc1SBen Gras /* not a valid conversion just eat a char */
16851ffecc1SBen Gras wc = *bytes;
16951ffecc1SBen Gras n = 1;
170ee8602a4SBen Gras (void)memset(&st, 0, sizeof(st));
17151ffecc1SBen Gras } else if (wc == 0) {
17251ffecc1SBen Gras break;
17351ffecc1SBen Gras }
17451ffecc1SBen Gras #ifdef DEBUG
17551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
17651ffecc1SBen Gras "ADDBYTES WIDE(0x%x [%s], %x) at (%d, %d), ate %d bytes\n",
17751ffecc1SBen Gras (unsigned) wc, unctrl((unsigned) wc), attr, y, x, n);
17851ffecc1SBen Gras #endif
17951ffecc1SBen Gras cc.vals[0] = wc;
18051ffecc1SBen Gras cc.elements = 1;
18151ffecc1SBen Gras cc.attributes = attr;
182*84d9c625SLionel Sambuc err = _cursesi_addwchar(win, &lp, &y, &x, &cc, char_interp);
18351ffecc1SBen Gras bytes += n;
18451ffecc1SBen Gras count -= n;
18551ffecc1SBen Gras #endif
18651ffecc1SBen Gras }
18751ffecc1SBen Gras
18851ffecc1SBen Gras SYNCH_OUT;
18951ffecc1SBen Gras
19051ffecc1SBen Gras #ifdef DEBUG
19151ffecc1SBen Gras for (i = 0; i < win->maxy; i++) {
19251ffecc1SBen Gras assert(win->alines[i]->sentinel == SENTINEL_VALUE);
19351ffecc1SBen Gras }
19451ffecc1SBen Gras #endif
19551ffecc1SBen Gras
19651ffecc1SBen Gras return (err);
19751ffecc1SBen Gras }
19851ffecc1SBen Gras
19951ffecc1SBen Gras /*
20051ffecc1SBen Gras * _cursesi_addbyte -
20151ffecc1SBen Gras * Internal function to add a byte and update the row and column
20251ffecc1SBen Gras * positions as appropriate. This function is only used in the narrow
203*84d9c625SLionel Sambuc * character version of curses. If update_cursor is non-zero then character
204*84d9c625SLionel Sambuc * interpretation.
20551ffecc1SBen Gras */
20651ffecc1SBen Gras int
_cursesi_addbyte(WINDOW * win,__LINE ** lp,int * y,int * x,int c,attr_t attr,int char_interp)20751ffecc1SBen Gras _cursesi_addbyte(WINDOW *win, __LINE **lp, int *y, int *x, int c,
208*84d9c625SLionel Sambuc attr_t attr, int char_interp)
20951ffecc1SBen Gras {
210*84d9c625SLionel Sambuc static char blank[] = " ";
211*84d9c625SLionel Sambuc int tabsize;
212*84d9c625SLionel Sambuc int newx, i;
21351ffecc1SBen Gras attr_t attributes;
21451ffecc1SBen Gras
215*84d9c625SLionel Sambuc if (char_interp) {
21651ffecc1SBen Gras switch (c) {
21751ffecc1SBen Gras case '\t':
218*84d9c625SLionel Sambuc tabsize = win->screen->TABSIZE;
21951ffecc1SBen Gras PSYNCH_OUT;
220*84d9c625SLionel Sambuc for (i = 0; i < (tabsize - (*x % tabsize)); i++) {
221*84d9c625SLionel Sambuc if (waddbytes(win, blank, 1) == ERR)
22251ffecc1SBen Gras return (ERR);
223*84d9c625SLionel Sambuc }
22451ffecc1SBen Gras PSYNCH_IN;
225*84d9c625SLionel Sambuc return (OK);
226*84d9c625SLionel Sambuc
227*84d9c625SLionel Sambuc case '\n':
228*84d9c625SLionel Sambuc PSYNCH_OUT;
229*84d9c625SLionel Sambuc wclrtoeol(win);
230*84d9c625SLionel Sambuc PSYNCH_IN;
231*84d9c625SLionel Sambuc (*lp)->flags |= __ISPASTEOL;
23251ffecc1SBen Gras break;
23351ffecc1SBen Gras
234*84d9c625SLionel Sambuc case '\r':
235*84d9c625SLionel Sambuc *x = 0;
236*84d9c625SLionel Sambuc win->curx = *x;
237*84d9c625SLionel Sambuc return (OK);
238*84d9c625SLionel Sambuc
239*84d9c625SLionel Sambuc case '\b':
240*84d9c625SLionel Sambuc if (--(*x) < 0)
241*84d9c625SLionel Sambuc *x = 0;
242*84d9c625SLionel Sambuc win->curx = *x;
243*84d9c625SLionel Sambuc return (OK);
244*84d9c625SLionel Sambuc }
245*84d9c625SLionel Sambuc }
246*84d9c625SLionel Sambuc
24751ffecc1SBen Gras #ifdef DEBUG
248*84d9c625SLionel Sambuc __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", win, *y, *x);
24951ffecc1SBen Gras #endif
25051ffecc1SBen Gras
251*84d9c625SLionel Sambuc if (char_interp && ((*lp)->flags & __ISPASTEOL)) {
25251ffecc1SBen Gras *x = 0;
25351ffecc1SBen Gras (*lp)->flags &= ~__ISPASTEOL;
25451ffecc1SBen Gras if (*y == win->scr_b) {
25551ffecc1SBen Gras #ifdef DEBUG
25651ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
25751ffecc1SBen Gras "ADDBYTES - on bottom "
25851ffecc1SBen Gras "of scrolling region\n");
25951ffecc1SBen Gras #endif
26051ffecc1SBen Gras if (!(win->flags & __SCROLLOK))
26151ffecc1SBen Gras return ERR;
26251ffecc1SBen Gras PSYNCH_OUT;
26351ffecc1SBen Gras scroll(win);
26451ffecc1SBen Gras PSYNCH_IN;
26551ffecc1SBen Gras } else {
26651ffecc1SBen Gras (*y)++;
26751ffecc1SBen Gras }
26851ffecc1SBen Gras *lp = win->alines[*y];
26951ffecc1SBen Gras if (c == '\n')
270*84d9c625SLionel Sambuc return (OK);
27151ffecc1SBen Gras }
27251ffecc1SBen Gras
273*84d9c625SLionel Sambuc #ifdef DEBUG
274*84d9c625SLionel Sambuc __CTRACE(__CTRACE_INPUT,
275*84d9c625SLionel Sambuc "ADDBYTES: 1: y = %d, x = %d, firstch = %d, lastch = %d\n",
276*84d9c625SLionel Sambuc *y, *x, *win->alines[*y]->firstchp,
277*84d9c625SLionel Sambuc *win->alines[*y]->lastchp);
278*84d9c625SLionel Sambuc #endif
279*84d9c625SLionel Sambuc
280*84d9c625SLionel Sambuc attributes = (win->wattr | attr) & (__ATTRIBUTES & ~__COLOR);
28151ffecc1SBen Gras if (attr & __COLOR)
28251ffecc1SBen Gras attributes |= attr & __COLOR;
28351ffecc1SBen Gras else if (win->wattr & __COLOR)
28451ffecc1SBen Gras attributes |= win->wattr & __COLOR;
285*84d9c625SLionel Sambuc
28651ffecc1SBen Gras /*
28751ffecc1SBen Gras * Always update the change pointers. Otherwise,
28851ffecc1SBen Gras * we could end up not displaying 'blank' characters
28951ffecc1SBen Gras * when overlapping windows are displayed.
29051ffecc1SBen Gras */
29151ffecc1SBen Gras newx = *x + win->ch_off;
29251ffecc1SBen Gras (*lp)->flags |= __ISDIRTY;
29351ffecc1SBen Gras /*
29451ffecc1SBen Gras * firstchp/lastchp are shared between
29551ffecc1SBen Gras * parent window and sub-window.
29651ffecc1SBen Gras */
29751ffecc1SBen Gras if (newx < *(*lp)->firstchp)
29851ffecc1SBen Gras *(*lp)->firstchp = newx;
29951ffecc1SBen Gras if (newx > *(*lp)->lastchp)
30051ffecc1SBen Gras *(*lp)->lastchp = newx;
30151ffecc1SBen Gras #ifdef DEBUG
302*84d9c625SLionel Sambuc __CTRACE(__CTRACE_INPUT, "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n",
30351ffecc1SBen Gras *(*lp)->firstchp, *(*lp)->lastchp,
30451ffecc1SBen Gras *(*lp)->firstchp - win->ch_off,
30551ffecc1SBen Gras *(*lp)->lastchp - win->ch_off);
30651ffecc1SBen Gras #endif
30751ffecc1SBen Gras if (win->bch != ' ' && c == ' ')
30851ffecc1SBen Gras (*lp)->line[*x].ch = win->bch;
30951ffecc1SBen Gras else
31051ffecc1SBen Gras (*lp)->line[*x].ch = c;
31151ffecc1SBen Gras
31251ffecc1SBen Gras if (attributes & __COLOR)
31351ffecc1SBen Gras (*lp)->line[*x].attr =
31451ffecc1SBen Gras attributes | (win->battr & ~__COLOR);
31551ffecc1SBen Gras else
31651ffecc1SBen Gras (*lp)->line[*x].attr = attributes | win->battr;
31751ffecc1SBen Gras
31851ffecc1SBen Gras if (*x == win->maxx - 1)
31951ffecc1SBen Gras (*lp)->flags |= __ISPASTEOL;
32051ffecc1SBen Gras else
32151ffecc1SBen Gras (*x)++;
322*84d9c625SLionel Sambuc
32351ffecc1SBen Gras #ifdef DEBUG
32451ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
325*84d9c625SLionel Sambuc "ADDBYTES: 2: y = %d, x = %d, firstch = %d, lastch = %d\n",
32651ffecc1SBen Gras *y, *x, *win->alines[*y]->firstchp,
32751ffecc1SBen Gras *win->alines[*y]->lastchp);
32851ffecc1SBen Gras #endif
32951ffecc1SBen Gras return (OK);
33051ffecc1SBen Gras }
33151ffecc1SBen Gras
33251ffecc1SBen Gras /*
33351ffecc1SBen Gras * _cursesi_addwchar -
33451ffecc1SBen Gras * Internal function to add a wide character and update the row
33551ffecc1SBen Gras * and column positions.
33651ffecc1SBen Gras */
33751ffecc1SBen Gras int
_cursesi_addwchar(WINDOW * win,__LINE ** lnp,int * y,int * x,const cchar_t * wch,int char_interp)33851ffecc1SBen Gras _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x,
339*84d9c625SLionel Sambuc const cchar_t *wch, int char_interp)
34051ffecc1SBen Gras {
34151ffecc1SBen Gras #ifndef HAVE_WCHAR
34251ffecc1SBen Gras return (ERR);
34351ffecc1SBen Gras #else
344*84d9c625SLionel Sambuc int sx = 0, ex = 0, cw = 0, i = 0, newx = 0, tabsize;
34551ffecc1SBen Gras __LDATA *lp = &win->alines[*y]->line[*x], *tp = NULL;
34651ffecc1SBen Gras nschar_t *np = NULL;
34751ffecc1SBen Gras cchar_t cc;
34851ffecc1SBen Gras attr_t attributes;
34951ffecc1SBen Gras
350*84d9c625SLionel Sambuc if (char_interp) {
35151ffecc1SBen Gras /* special characters handling */
35251ffecc1SBen Gras switch (wch->vals[0]) {
35351ffecc1SBen Gras case L'\b':
35451ffecc1SBen Gras if (--*x < 0)
35551ffecc1SBen Gras *x = 0;
35651ffecc1SBen Gras win->curx = *x;
35751ffecc1SBen Gras return OK;
35851ffecc1SBen Gras case L'\r':
35951ffecc1SBen Gras *x = 0;
360*84d9c625SLionel Sambuc win->curx = *x;
36151ffecc1SBen Gras return OK;
36251ffecc1SBen Gras case L'\n':
36351ffecc1SBen Gras wclrtoeol(win);
36451ffecc1SBen Gras PSYNCH_IN;
36551ffecc1SBen Gras *x = 0;
36651ffecc1SBen Gras (*lnp)->flags &= ~__ISPASTEOL;
36751ffecc1SBen Gras if (*y == win->scr_b) {
36851ffecc1SBen Gras if (!(win->flags & __SCROLLOK))
36951ffecc1SBen Gras return ERR;
37051ffecc1SBen Gras PSYNCH_OUT;
37151ffecc1SBen Gras scroll(win);
37251ffecc1SBen Gras PSYNCH_IN;
37351ffecc1SBen Gras } else {
37451ffecc1SBen Gras (*y)++;
37551ffecc1SBen Gras }
37651ffecc1SBen Gras PSYNCH_OUT;
37751ffecc1SBen Gras return OK;
37851ffecc1SBen Gras case L'\t':
37951ffecc1SBen Gras cc.vals[0] = L' ';
38051ffecc1SBen Gras cc.elements = 1;
38151ffecc1SBen Gras cc.attributes = win->wattr;
382*84d9c625SLionel Sambuc tabsize = win->screen->TABSIZE;
383*84d9c625SLionel Sambuc for (i = 0; i < tabsize - (*x % tabsize); i++) {
38451ffecc1SBen Gras if (wadd_wch(win, &cc) == ERR)
38551ffecc1SBen Gras return ERR;
38651ffecc1SBen Gras }
38751ffecc1SBen Gras return OK;
38851ffecc1SBen Gras }
389*84d9c625SLionel Sambuc }
39051ffecc1SBen Gras
39151ffecc1SBen Gras /* check for non-spacing character */
39251ffecc1SBen Gras if (!wcwidth(wch->vals[0])) {
39351ffecc1SBen Gras #ifdef DEBUG
39451ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
39551ffecc1SBen Gras "_cursesi_addwchar: char '%c' is non-spacing\n",
39651ffecc1SBen Gras wch->vals[0]);
39751ffecc1SBen Gras #endif /* DEBUG */
39851ffecc1SBen Gras cw = WCOL(*lp);
39951ffecc1SBen Gras if (cw < 0) {
40051ffecc1SBen Gras lp += cw;
40151ffecc1SBen Gras *x += cw;
40251ffecc1SBen Gras }
40351ffecc1SBen Gras for (i = 0; i < wch->elements; i++) {
40451ffecc1SBen Gras if (!(np = (nschar_t *) malloc(sizeof(nschar_t))))
40551ffecc1SBen Gras return ERR;;
40651ffecc1SBen Gras np->ch = wch->vals[i];
40751ffecc1SBen Gras np->next = lp->nsp;
40851ffecc1SBen Gras lp->nsp = np;
40951ffecc1SBen Gras }
41051ffecc1SBen Gras (*lnp)->flags |= __ISDIRTY;
41151ffecc1SBen Gras newx = *x + win->ch_off;
41251ffecc1SBen Gras if (newx < *(*lnp)->firstchp)
41351ffecc1SBen Gras *(*lnp)->firstchp = newx;
41451ffecc1SBen Gras if (newx > *(*lnp)->lastchp)
41551ffecc1SBen Gras *(*lnp)->lastchp = newx;
41651ffecc1SBen Gras __touchline(win, *y, *x, *x);
41751ffecc1SBen Gras return OK;
41851ffecc1SBen Gras }
41951ffecc1SBen Gras /* check for new line first */
420*84d9c625SLionel Sambuc if (char_interp && ((*lnp)->flags & __ISPASTEOL)) {
42151ffecc1SBen Gras *x = 0;
42251ffecc1SBen Gras (*lnp)->flags &= ~__ISPASTEOL;
42351ffecc1SBen Gras if (*y == win->scr_b) {
42451ffecc1SBen Gras if (!(win->flags & __SCROLLOK))
42551ffecc1SBen Gras return ERR;
42651ffecc1SBen Gras PSYNCH_OUT;
42751ffecc1SBen Gras scroll(win);
42851ffecc1SBen Gras PSYNCH_IN;
42951ffecc1SBen Gras } else {
43051ffecc1SBen Gras (*y)++;
43151ffecc1SBen Gras }
43251ffecc1SBen Gras (*lnp) = win->alines[*y];
43351ffecc1SBen Gras lp = &win->alines[*y]->line[*x];
43451ffecc1SBen Gras }
43551ffecc1SBen Gras /* clear out the current character */
43651ffecc1SBen Gras cw = WCOL(*lp);
43751ffecc1SBen Gras if (cw >= 0) {
43851ffecc1SBen Gras sx = *x;
43951ffecc1SBen Gras } else {
44051ffecc1SBen Gras for (sx = *x - 1; sx >= max(*x + cw, 0); sx--) {
44151ffecc1SBen Gras #ifdef DEBUG
44251ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
44351ffecc1SBen Gras "_cursesi_addwchar: clear current char (%d,%d)\n",
44451ffecc1SBen Gras *y, sx);
44551ffecc1SBen Gras #endif /* DEBUG */
44651ffecc1SBen Gras tp = &win->alines[*y]->line[sx];
44751ffecc1SBen Gras tp->ch = (wchar_t) btowc((int) win->bch);
44851ffecc1SBen Gras if (_cursesi_copy_nsp(win->bnsp, tp) == ERR)
44951ffecc1SBen Gras return ERR;
45051ffecc1SBen Gras
45151ffecc1SBen Gras tp->attr = win->battr;
45251ffecc1SBen Gras SET_WCOL(*tp, 1);
45351ffecc1SBen Gras }
45451ffecc1SBen Gras sx = *x + cw;
45551ffecc1SBen Gras (*lnp)->flags |= __ISDIRTY;
45651ffecc1SBen Gras newx = sx + win->ch_off;
45751ffecc1SBen Gras if (newx < *(*lnp)->firstchp)
45851ffecc1SBen Gras *(*lnp)->firstchp = newx;
45951ffecc1SBen Gras }
46051ffecc1SBen Gras
46151ffecc1SBen Gras /* check for enough space before the end of line */
46251ffecc1SBen Gras cw = wcwidth(wch->vals[0]);
46351ffecc1SBen Gras if (cw < 0)
46451ffecc1SBen Gras cw = 1;
465*84d9c625SLionel Sambuc
46651ffecc1SBen Gras if (cw > win->maxx - *x) {
46751ffecc1SBen Gras #ifdef DEBUG
46851ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
46951ffecc1SBen Gras "_cursesi_addwchar: clear EOL (%d,%d)\n",
47051ffecc1SBen Gras *y, *x);
47151ffecc1SBen Gras #endif /* DEBUG */
47251ffecc1SBen Gras (*lnp)->flags |= __ISDIRTY;
47351ffecc1SBen Gras newx = *x + win->ch_off;
47451ffecc1SBen Gras if (newx < *(*lnp)->firstchp)
47551ffecc1SBen Gras *(*lnp)->firstchp = newx;
47651ffecc1SBen Gras for (tp = lp; *x < win->maxx; tp++, (*x)++) {
47751ffecc1SBen Gras tp->ch = (wchar_t) btowc((int) win->bch);
47851ffecc1SBen Gras if (_cursesi_copy_nsp(win->bnsp, tp) == ERR)
47951ffecc1SBen Gras return ERR;
48051ffecc1SBen Gras tp->attr = win->battr;
48151ffecc1SBen Gras SET_WCOL(*tp, 1);
48251ffecc1SBen Gras }
48351ffecc1SBen Gras newx = win->maxx - 1 + win->ch_off;
48451ffecc1SBen Gras if (newx > *(*lnp)->lastchp)
48551ffecc1SBen Gras *(*lnp)->lastchp = newx;
48651ffecc1SBen Gras __touchline(win, *y, sx, (int) win->maxx - 1);
48751ffecc1SBen Gras sx = *x = 0;
48851ffecc1SBen Gras if (*y == win->scr_b) {
48951ffecc1SBen Gras if (!(win->flags & __SCROLLOK))
49051ffecc1SBen Gras return ERR;
49151ffecc1SBen Gras PSYNCH_OUT;
49251ffecc1SBen Gras scroll(win);
49351ffecc1SBen Gras PSYNCH_IN;
49451ffecc1SBen Gras } else {
49551ffecc1SBen Gras (*y)++;
49651ffecc1SBen Gras }
49751ffecc1SBen Gras lp = &win->alines[*y]->line[0];
49851ffecc1SBen Gras (*lnp) = win->alines[*y];
49951ffecc1SBen Gras }
50051ffecc1SBen Gras win->cury = *y;
50151ffecc1SBen Gras
50251ffecc1SBen Gras /* add spacing character */
50351ffecc1SBen Gras #ifdef DEBUG
50451ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
50551ffecc1SBen Gras "_cursesi_addwchar: add character (%d,%d) 0x%x\n",
50651ffecc1SBen Gras *y, *x, wch->vals[0]);
50751ffecc1SBen Gras #endif /* DEBUG */
50851ffecc1SBen Gras (*lnp)->flags |= __ISDIRTY;
50951ffecc1SBen Gras newx = *x + win->ch_off;
51051ffecc1SBen Gras if (newx < *(*lnp)->firstchp)
51151ffecc1SBen Gras *(*lnp)->firstchp = newx;
51251ffecc1SBen Gras if (lp->nsp) {
51351ffecc1SBen Gras __cursesi_free_nsp(lp->nsp);
51451ffecc1SBen Gras lp->nsp = NULL;
51551ffecc1SBen Gras }
51651ffecc1SBen Gras
51751ffecc1SBen Gras lp->ch = wch->vals[0];
51851ffecc1SBen Gras
51951ffecc1SBen Gras attributes = (win->wattr | wch->attributes)
52051ffecc1SBen Gras & (WA_ATTRIBUTES & ~__COLOR);
52151ffecc1SBen Gras if (wch->attributes & __COLOR)
52251ffecc1SBen Gras attributes |= wch->attributes & __COLOR;
52351ffecc1SBen Gras else if (win->wattr & __COLOR)
52451ffecc1SBen Gras attributes |= win->wattr & __COLOR;
52551ffecc1SBen Gras if (attributes & __COLOR)
52651ffecc1SBen Gras lp->attr = attributes | (win->battr & ~__COLOR);
52751ffecc1SBen Gras else
52851ffecc1SBen Gras lp->attr = attributes | win->battr;
52951ffecc1SBen Gras
53051ffecc1SBen Gras SET_WCOL(*lp, cw);
53151ffecc1SBen Gras
53251ffecc1SBen Gras #ifdef DEBUG
53351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
53451ffecc1SBen Gras "_cursesi_addwchar: add spacing char 0x%x, attr 0x%x\n",
53551ffecc1SBen Gras lp->ch, lp->attr);
53651ffecc1SBen Gras #endif /* DEBUG */
53751ffecc1SBen Gras
53851ffecc1SBen Gras if (wch->elements > 1) {
53951ffecc1SBen Gras for (i = 1; i < wch->elements; i++) {
54051ffecc1SBen Gras np = (nschar_t *)malloc(sizeof(nschar_t));
54151ffecc1SBen Gras if (!np)
54251ffecc1SBen Gras return ERR;;
54351ffecc1SBen Gras np->ch = wch->vals[i];
54451ffecc1SBen Gras np->next = lp->nsp;
54551ffecc1SBen Gras #ifdef DEBUG
54651ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
54751ffecc1SBen Gras "_cursesi_addwchar: add non-spacing char 0x%x\n", np->ch);
54851ffecc1SBen Gras #endif /* DEBUG */
54951ffecc1SBen Gras lp->nsp = np;
55051ffecc1SBen Gras }
55151ffecc1SBen Gras }
55251ffecc1SBen Gras #ifdef DEBUG
55351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: non-spacing list header: %p\n",
55451ffecc1SBen Gras lp->nsp);
55551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: add rest columns (%d:%d)\n",
55651ffecc1SBen Gras sx + 1, sx + cw - 1);
55751ffecc1SBen Gras #endif /* DEBUG */
55851ffecc1SBen Gras for (tp = lp + 1, *x = sx + 1; *x - sx <= cw - 1; tp++, (*x)++) {
55951ffecc1SBen Gras if (tp->nsp) {
56051ffecc1SBen Gras __cursesi_free_nsp(tp->nsp);
56151ffecc1SBen Gras tp->nsp = NULL;
56251ffecc1SBen Gras }
56351ffecc1SBen Gras tp->ch = wch->vals[0];
56451ffecc1SBen Gras tp->attr = lp->attr & WA_ATTRIBUTES;
56551ffecc1SBen Gras /* Mark as "continuation" cell */
56651ffecc1SBen Gras tp->attr |= __WCWIDTH;
56751ffecc1SBen Gras }
568*84d9c625SLionel Sambuc
56951ffecc1SBen Gras if (*x == win->maxx) {
57051ffecc1SBen Gras (*lnp)->flags |= __ISPASTEOL;
57151ffecc1SBen Gras newx = win->maxx - 1 + win->ch_off;
57251ffecc1SBen Gras if (newx > *(*lnp)->lastchp)
57351ffecc1SBen Gras *(*lnp)->lastchp = newx;
57451ffecc1SBen Gras __touchline(win, *y, sx, (int) win->maxx - 1);
57551ffecc1SBen Gras win->curx = sx;
57651ffecc1SBen Gras } else {
57751ffecc1SBen Gras win->curx = *x;
57851ffecc1SBen Gras
57951ffecc1SBen Gras /* clear the remining of the current characer */
58051ffecc1SBen Gras if (*x && *x < win->maxx) {
58151ffecc1SBen Gras ex = sx + cw;
58251ffecc1SBen Gras tp = &win->alines[*y]->line[ex];
58351ffecc1SBen Gras while (ex < win->maxx && WCOL(*tp) < 0) {
58451ffecc1SBen Gras #ifdef DEBUG
58551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
58651ffecc1SBen Gras "_cursesi_addwchar: clear "
58751ffecc1SBen Gras "remaining of current char (%d,%d)nn",
58851ffecc1SBen Gras *y, ex);
58951ffecc1SBen Gras #endif /* DEBUG */
59051ffecc1SBen Gras tp->ch = (wchar_t) btowc((int) win->bch);
59151ffecc1SBen Gras if (_cursesi_copy_nsp(win->bnsp, tp) == ERR)
59251ffecc1SBen Gras return ERR;
59351ffecc1SBen Gras tp->attr = win->battr;
59451ffecc1SBen Gras SET_WCOL(*tp, 1);
59551ffecc1SBen Gras tp++, ex++;
59651ffecc1SBen Gras }
59751ffecc1SBen Gras newx = ex - 1 + win->ch_off;
59851ffecc1SBen Gras if (newx > *(*lnp)->lastchp)
59951ffecc1SBen Gras *(*lnp)->lastchp = newx;
60051ffecc1SBen Gras __touchline(win, *y, sx, ex - 1);
60151ffecc1SBen Gras }
60251ffecc1SBen Gras }
60351ffecc1SBen Gras
60451ffecc1SBen Gras #ifdef DEBUG
60551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "add_wch: %d : 0x%x\n", lp->ch, lp->attr);
60651ffecc1SBen Gras #endif /* DEBUG */
60751ffecc1SBen Gras return OK;
60851ffecc1SBen Gras #endif
60951ffecc1SBen Gras }
610