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