1*6348e3f3Sblymn /* $NetBSD: addbytes.c,v 1.70 2024/12/23 02:58:03 blymn Exp $ */ 2716747aaSmikel 361f28255Scgd /* 4d29088daScgd * Copyright (c) 1987, 1993, 1994 5019bbd13Scgd * The Regents of the University of California. All rights reserved. 661f28255Scgd * 761f28255Scgd * Redistribution and use in source and binary forms, with or without 861f28255Scgd * modification, are permitted provided that the following conditions 961f28255Scgd * are met: 1061f28255Scgd * 1. Redistributions of source code must retain the above copyright 1161f28255Scgd * notice, this list of conditions and the following disclaimer. 1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright 1361f28255Scgd * notice, this list of conditions and the following disclaimer in the 1461f28255Scgd * documentation and/or other materials provided with the distribution. 15eb7c1594Sagc * 3. Neither the name of the University nor the names of its contributors 1661f28255Scgd * may be used to endorse or promote products derived from this software 1761f28255Scgd * without specific prior written permission. 1861f28255Scgd * 1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2961f28255Scgd * SUCH DAMAGE. 3061f28255Scgd */ 3161f28255Scgd 32716747aaSmikel #include <sys/cdefs.h> 3361f28255Scgd #ifndef lint 34716747aaSmikel #if 0 35d29088daScgd static char sccsid[] = "@(#)addbytes.c 8.4 (Berkeley) 5/4/94"; 36716747aaSmikel #else 37*6348e3f3Sblymn __RCSID("$NetBSD: addbytes.c,v 1.70 2024/12/23 02:58:03 blymn Exp $"); 38716747aaSmikel #endif 3961f28255Scgd #endif /* not lint */ 4061f28255Scgd 41e124de36Sblymn #include <stdlib.h> 42115137adStnozaki #include <string.h> 43d29088daScgd #include "curses.h" 4423464ee5Sblymn #include "curses_private.h" 458d259104Sblymn #ifdef DEBUG 468d259104Sblymn #include <assert.h> 478d259104Sblymn #endif 4861f28255Scgd 49aaf74682Sblymn #ifndef _CURSES_USE_MACROS 50aaf74682Sblymn 51aaf74682Sblymn /* 52aaf74682Sblymn * addbytes -- 53609d11bcSrillig * Add the characters to the current position in stdscr. 54aaf74682Sblymn */ 55aaf74682Sblymn int 56aaf74682Sblymn addbytes(const char *bytes, int count) 57aaf74682Sblymn { 5891804696Sroy 5969b405aaSblymn return _cursesi_waddbytes(stdscr, bytes, count, 0, 1); 60aaf74682Sblymn } 61aaf74682Sblymn 6261f28255Scgd /* 6362a3457dSmycroft * waddbytes -- 64609d11bcSrillig * Add the characters to the current position in the given window. 6561f28255Scgd */ 6662a3457dSmycroft int 67aaf74682Sblymn waddbytes(WINDOW *win, const char *bytes, int count) 68aaf74682Sblymn { 6991804696Sroy 7069b405aaSblymn return _cursesi_waddbytes(win, bytes, count, 0, 1); 71aaf74682Sblymn } 72aaf74682Sblymn 73aaf74682Sblymn /* 74aaf74682Sblymn * mvaddbytes -- 75aaf74682Sblymn * Add the characters to stdscr at the location given. 76aaf74682Sblymn */ 77aaf74682Sblymn int 78aaf74682Sblymn mvaddbytes(int y, int x, const char *bytes, int count) 79aaf74682Sblymn { 8091804696Sroy 81aaf74682Sblymn return mvwaddbytes(stdscr, y, x, bytes, count); 82aaf74682Sblymn } 83aaf74682Sblymn 84aaf74682Sblymn /* 85aaf74682Sblymn * mvwaddbytes -- 86aaf74682Sblymn * Add the characters to the given window at the location given. 87aaf74682Sblymn */ 88aaf74682Sblymn int 89aaf74682Sblymn mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count) 90aaf74682Sblymn { 9191804696Sroy 922a780e62Sblymn if (wmove(win, y, x) == ERR) 93aaf74682Sblymn return ERR; 94aaf74682Sblymn 9569b405aaSblymn return _cursesi_waddbytes(win, bytes, count, 0, 1); 96aaf74682Sblymn } 97aaf74682Sblymn 98aaf74682Sblymn #endif 99aaf74682Sblymn 100aaf74682Sblymn int 101aaf74682Sblymn __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr) 10261f28255Scgd { 10391804696Sroy 10469b405aaSblymn return _cursesi_waddbytes(win, bytes, count, attr, 1); 10569b405aaSblymn } 10669b405aaSblymn 10769b405aaSblymn /* 10869b405aaSblymn * _cursesi_waddbytes -- 109609d11bcSrillig * Add the characters to the current position in the given window. 11069b405aaSblymn * if char_interp is non-zero then character interpretation is done on 11169b405aaSblymn * the byte (i.e. \n to newline, \r to carriage return, \b to backspace 11269b405aaSblymn * and so on). 11369b405aaSblymn */ 11469b405aaSblymn int 11569b405aaSblymn _cursesi_waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr, 11669b405aaSblymn int char_interp) 11769b405aaSblymn { 118609d11bcSrillig int *py = &win->cury, *px = &win->curx, err; 119019bbd13Scgd __LINE *lp; 120e124de36Sblymn #ifdef HAVE_WCHAR 1219c6a0e32Sblymn int n; 122e124de36Sblymn cchar_t cc; 123e124de36Sblymn wchar_t wc; 124c71a9f1dStnozaki mbstate_t st; 125e124de36Sblymn #else 126e124de36Sblymn int c; 127e124de36Sblymn #endif 1288d259104Sblymn #ifdef DEBUG 1298d259104Sblymn int i; 1308d259104Sblymn 131*6348e3f3Sblymn if (__predict_false(win == NULL)) 132*6348e3f3Sblymn return ERR; 133*6348e3f3Sblymn 1348d259104Sblymn for (i = 0; i < win->maxy; i++) { 13543d5eb45Sroy assert(win->alines[i]->sentinel == SENTINEL_VALUE); 1368d259104Sblymn } 137e124de36Sblymn 138e124de36Sblymn __CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count); 1398d259104Sblymn #endif 14061f28255Scgd 141e124de36Sblymn err = OK; 142609d11bcSrillig lp = win->alines[*py]; 14362a3457dSmycroft 144c71a9f1dStnozaki #ifdef HAVE_WCHAR 145115137adStnozaki (void)memset(&st, 0, sizeof(st)); 146c71a9f1dStnozaki #endif 147e124de36Sblymn while (count > 0) { 148e124de36Sblymn #ifndef HAVE_WCHAR 149716747aaSmikel c = *bytes++; 1501f221324Sjdc __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n", 151609d11bcSrillig c, attr, *py, *px); 152609d11bcSrillig err = _cursesi_addbyte(win, &lp, py, px, c, attr, char_interp); 153e124de36Sblymn count--; 154e124de36Sblymn #else 155e124de36Sblymn /* 156609d11bcSrillig * For wide-character support only, try to convert the 157e124de36Sblymn * given string into a wide character - we do this because 158e124de36Sblymn * this is how ncurses behaves (not that I think this is 159e124de36Sblymn * actually the correct thing to do but if we don't do it 160e124de36Sblymn * a lot of things that rely on this behaviour will break 161e124de36Sblymn * and we will be blamed). If the conversion succeeds 162e124de36Sblymn * then we eat the n characters used to make the wide char 163e124de36Sblymn * from the string. 164e124de36Sblymn */ 165c71a9f1dStnozaki n = (int)mbrtowc(&wc, bytes, (size_t)count, &st); 166c71a9f1dStnozaki if (n < 0) { 167c71a9f1dStnozaki /* not a valid conversion just eat a char */ 168e124de36Sblymn wc = *bytes; 169e124de36Sblymn n = 1; 170b341a73aSjoerg (void)memset(&st, 0, sizeof(st)); 171c71a9f1dStnozaki } else if (wc == 0) { 172c71a9f1dStnozaki break; 173e124de36Sblymn } 1747a398f9fSblymn 175e124de36Sblymn __CTRACE(__CTRACE_INPUT, 1769c6a0e32Sblymn "ADDBYTES WIDE(0x%04x [%s], %x) at (%d, %d), ate %d bytes\n", 177609d11bcSrillig (unsigned)wc, unctrl((unsigned)wc), attr, *py, *px, n); 178e124de36Sblymn cc.vals[0] = wc; 179e124de36Sblymn cc.elements = 1; 180e124de36Sblymn cc.attributes = attr; 181609d11bcSrillig err = _cursesi_addwchar(win, &lp, py, px, &cc, char_interp); 182e124de36Sblymn bytes += n; 1839c6a0e32Sblymn count -= n; 184e124de36Sblymn #endif 185e124de36Sblymn } 186e124de36Sblymn 187e124de36Sblymn #ifdef DEBUG 188e124de36Sblymn for (i = 0; i < win->maxy; i++) { 18943d5eb45Sroy assert(win->alines[i]->sentinel == SENTINEL_VALUE); 190e124de36Sblymn } 191e124de36Sblymn #endif 192e124de36Sblymn 193e124de36Sblymn return (err); 194e124de36Sblymn } 195e124de36Sblymn 196e124de36Sblymn /* 197e124de36Sblymn * _cursesi_addbyte - 198e124de36Sblymn * Internal function to add a byte and update the row and column 199540f2c17Suwe * positions as appropriate. If char_interp is non-zero then 200540f2c17Suwe * character interpretation is done on the byte. This function is 201540f2c17Suwe * only used in the narrow character version of curses. 202e124de36Sblymn */ 203e124de36Sblymn int 204e124de36Sblymn _cursesi_addbyte(WINDOW *win, __LINE **lp, int *y, int *x, int c, 20569b405aaSblymn attr_t attr, int char_interp) 206e124de36Sblymn { 20769b405aaSblymn static char blank[] = " "; 2082e2213efSroy int tabsize; 209f1942931Sblymn int newx, i, wcols; 21069b405aaSblymn attr_t attributes; 211e124de36Sblymn 212*6348e3f3Sblymn if (__predict_false(win == NULL)) 213*6348e3f3Sblymn return ERR; 214*6348e3f3Sblymn 21569b405aaSblymn if (char_interp) { 21661f28255Scgd switch (c) { 21761f28255Scgd case '\t': 2182e2213efSroy tabsize = win->screen->TABSIZE; 21956b8322bSchristos newx = tabsize - (*x % tabsize); 2207a398f9fSblymn /* if at the bottom of the window and 2217a398f9fSblymn not allowed to scroll then just do 2227a398f9fSblymn what we can */ 2237a398f9fSblymn if ((*y == win->scr_b) && 2247a398f9fSblymn !(win->flags & __SCROLLOK)) { 2257a398f9fSblymn if ((*lp)->flags & __ISPASTEOL) { 2267a398f9fSblymn return OK; 2277a398f9fSblymn } 2287a398f9fSblymn 2297a398f9fSblymn if (*x + newx > win->maxx - 1) 2307a398f9fSblymn newx = win->maxx - *x - 1; 2317a398f9fSblymn } 2327a398f9fSblymn 23356b8322bSchristos for (i = 0; i < newx; i++) { 23469b405aaSblymn if (waddbytes(win, blank, 1) == ERR) 23584fe414eSroy return ERR; 23669b405aaSblymn } 23784fe414eSroy return OK; 23869b405aaSblymn 23969b405aaSblymn case '\n': 24069b405aaSblymn wclrtoeol(win); 24169b405aaSblymn (*lp)->flags |= __ISPASTEOL; 24261f28255Scgd break; 24361f28255Scgd 24469b405aaSblymn case '\r': 24569b405aaSblymn *x = 0; 24684fe414eSroy return OK; 24769b405aaSblymn 24869b405aaSblymn case '\b': 24969b405aaSblymn if (--(*x) < 0) 25069b405aaSblymn *x = 0; 25184fe414eSroy return OK; 25269b405aaSblymn } 25369b405aaSblymn } 25469b405aaSblymn 25569b405aaSblymn __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", win, *y, *x); 256019bbd13Scgd 25769b405aaSblymn if (char_interp && ((*lp)->flags & __ISPASTEOL)) { 258e124de36Sblymn *x = 0; 259e124de36Sblymn (*lp)->flags &= ~__ISPASTEOL; 260e124de36Sblymn if (*y == win->scr_b) { 2611f221324Sjdc __CTRACE(__CTRACE_INPUT, 262b09154d5Srin "ADDBYTES - on bottom of scrolling region\n"); 263c841017dSdsl if (!(win->flags & __SCROLLOK)) 264c841017dSdsl return ERR; 26561f28255Scgd scroll(win); 266019bbd13Scgd } else { 267e124de36Sblymn (*y)++; 268019bbd13Scgd } 26943d5eb45Sroy *lp = win->alines[*y]; 270019bbd13Scgd if (c == '\n') 27184fe414eSroy return OK; 272019bbd13Scgd } 273019bbd13Scgd 27469b405aaSblymn __CTRACE(__CTRACE_INPUT, 27569b405aaSblymn "ADDBYTES: 1: y = %d, x = %d, firstch = %d, lastch = %d\n", 276b09154d5Srin *y, *x, *win->alines[*y]->firstchp, *win->alines[*y]->lastchp); 27769b405aaSblymn 27869b405aaSblymn attributes = (win->wattr | attr) & (__ATTRIBUTES & ~__COLOR); 27940b39f92Sjdc if (attr & __COLOR) 28040b39f92Sjdc attributes |= attr & __COLOR; 28140b39f92Sjdc else if (win->wattr & __COLOR) 28240b39f92Sjdc attributes |= win->wattr & __COLOR; 28369b405aaSblymn 284f1942931Sblymn 285f1942931Sblymn wcols = wcwidth(c); 286f1942931Sblymn if (wcols < 0) 287f1942931Sblymn wcols = 1; 288f1942931Sblymn 28902559eb6Sjdc /* 29002559eb6Sjdc * Always update the change pointers. Otherwise, 29102559eb6Sjdc * we could end up not displaying 'blank' characters 29202559eb6Sjdc * when overlapping windows are displayed. 29302559eb6Sjdc */ 294e124de36Sblymn newx = *x + win->ch_off; 295e124de36Sblymn (*lp)->flags |= __ISDIRTY; 2968e3f5589Sjdc /* 2978e3f5589Sjdc * firstchp/lastchp are shared between 2988e3f5589Sjdc * parent window and sub-window. 2998e3f5589Sjdc */ 300e124de36Sblymn if (newx < *(*lp)->firstchp) 301e124de36Sblymn *(*lp)->firstchp = newx; 302ee6c5161Sblymn 303e124de36Sblymn if (newx > *(*lp)->lastchp) 304e124de36Sblymn *(*lp)->lastchp = newx; 30569b405aaSblymn __CTRACE(__CTRACE_INPUT, "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", 306e124de36Sblymn *(*lp)->firstchp, *(*lp)->lastchp, 307e124de36Sblymn *(*lp)->firstchp - win->ch_off, 308e124de36Sblymn *(*lp)->lastchp - win->ch_off); 309f1942931Sblymn if (win->bch != ' ' && c == ' ') { 310e124de36Sblymn (*lp)->line[*x].ch = win->bch; 311f1942931Sblymn #ifdef HAVE_CHAR 312f1942931Sblymn (*lp)->line[*x].wcols = win->wcols; 313f1942931Sblymn #endif 314f1942931Sblymn } else { 315e124de36Sblymn (*lp)->line[*x].ch = c; 316f1942931Sblymn #ifdef HAVE_CHAR 317f1942931Sblymn (*lp)->line[*x].wcols = wcols; 318f1942931Sblymn #endif 319f1942931Sblymn } 320e124de36Sblymn 321ee6c5161Sblymn (*lp)->line[*x].cflags &= ~ (CA_BACKGROUND | CA_CONTINUATION); 322a7d2c216Sblymn 323978ab4adSjdc if (attributes & __COLOR) 324e124de36Sblymn (*lp)->line[*x].attr = 325978ab4adSjdc attributes | (win->battr & ~__COLOR); 326978ab4adSjdc else 327e124de36Sblymn (*lp)->line[*x].attr = attributes | win->battr; 328e124de36Sblymn 329e124de36Sblymn if (*x == win->maxx - 1) 330e124de36Sblymn (*lp)->flags |= __ISPASTEOL; 331019bbd13Scgd else 332e124de36Sblymn (*x)++; 33369b405aaSblymn 3341f221324Sjdc __CTRACE(__CTRACE_INPUT, 33569b405aaSblymn "ADDBYTES: 2: y = %d, x = %d, firstch = %d, lastch = %d\n", 336b09154d5Srin *y, *x, *win->alines[*y]->firstchp, *win->alines[*y]->lastchp); 3371369811dSroy __sync(win); 33884fe414eSroy return OK; 33961f28255Scgd } 340e124de36Sblymn 341e124de36Sblymn /* 342e124de36Sblymn * _cursesi_addwchar - 343e124de36Sblymn * Internal function to add a wide character and update the row 344e124de36Sblymn * and column positions. 345e124de36Sblymn */ 346e124de36Sblymn int 347e124de36Sblymn _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x, 34869b405aaSblymn const cchar_t *wch, int char_interp) 349e124de36Sblymn { 350e124de36Sblymn #ifndef HAVE_WCHAR 35184fe414eSroy return ERR; 352e124de36Sblymn #else 3532e2213efSroy int sx = 0, ex = 0, cw = 0, i = 0, newx = 0, tabsize; 35443d5eb45Sroy __LDATA *lp = &win->alines[*y]->line[*x], *tp = NULL; 355e124de36Sblymn nschar_t *np = NULL; 356e124de36Sblymn cchar_t cc; 357e124de36Sblymn attr_t attributes; 358e124de36Sblymn 359*6348e3f3Sblymn if (__predict_false(win == NULL)) 360*6348e3f3Sblymn return ERR; 361*6348e3f3Sblymn 36269b405aaSblymn if (char_interp) { 363e124de36Sblymn /* special characters handling */ 364e124de36Sblymn switch (wch->vals[0]) { 365e124de36Sblymn case L'\b': 366e124de36Sblymn if (--*x < 0) 367e124de36Sblymn *x = 0; 368e124de36Sblymn return OK; 369e124de36Sblymn case L'\r': 370194f45e1Sjdc *x = 0; 371e124de36Sblymn return OK; 372e124de36Sblymn case L'\n': 373e124de36Sblymn if (*y == win->scr_b) { 374e124de36Sblymn if (!(win->flags & __SCROLLOK)) 375e124de36Sblymn return ERR; 37673328adfSblymn wclrtoeol(win); 377e124de36Sblymn scroll(win); 378e124de36Sblymn } else { 37973328adfSblymn wclrtoeol(win); 380e124de36Sblymn (*y)++; 381e124de36Sblymn } 38273328adfSblymn *x = 0; 38373328adfSblymn (*lnp)->flags &= ~__ISPASTEOL; 384e124de36Sblymn return OK; 385e124de36Sblymn case L'\t': 386e124de36Sblymn cc.vals[0] = L' '; 387e124de36Sblymn cc.elements = 1; 388e124de36Sblymn cc.attributes = win->wattr; 3892e2213efSroy tabsize = win->screen->TABSIZE; 39056b8322bSchristos newx = tabsize - (*x % tabsize); 3917a398f9fSblymn 3927a398f9fSblymn /* if at the bottom of the window and 3937a398f9fSblymn not allowed to scroll then just do 3947a398f9fSblymn what we can */ 3957a398f9fSblymn if ((*y == win->scr_b) && 3967a398f9fSblymn !(win->flags & __SCROLLOK)) { 3977a398f9fSblymn if ((*lnp)->flags & __ISPASTEOL) { 39873328adfSblymn return ERR; 3997a398f9fSblymn } 4007a398f9fSblymn 4017a398f9fSblymn if (*x + newx > win->maxx - 1) 4027a398f9fSblymn newx = win->maxx - *x - 1; 4037a398f9fSblymn } 4047a398f9fSblymn 40556b8322bSchristos for (i = 0; i < newx; i++) { 406e124de36Sblymn if (wadd_wch(win, &cc) == ERR) 407e124de36Sblymn return ERR; 408e124de36Sblymn } 409e124de36Sblymn return OK; 410e124de36Sblymn } 41169b405aaSblymn } 412e124de36Sblymn 413e124de36Sblymn /* check for non-spacing character */ 414e124de36Sblymn if (!wcwidth(wch->vals[0])) { 415e124de36Sblymn __CTRACE(__CTRACE_INPUT, 416e124de36Sblymn "_cursesi_addwchar: char '%c' is non-spacing\n", 417e124de36Sblymn wch->vals[0]); 418f1942931Sblymn cw = (*lp).wcols; 419e124de36Sblymn if (cw < 0) { 420e124de36Sblymn lp += cw; 421e124de36Sblymn *x += cw; 422e124de36Sblymn } 423e124de36Sblymn for (i = 0; i < wch->elements; i++) { 424e124de36Sblymn if (!(np = (nschar_t *) malloc(sizeof(nschar_t)))) 4257af2475fSrillig return ERR; 426e124de36Sblymn np->ch = wch->vals[i]; 427e124de36Sblymn np->next = lp->nsp; 428e124de36Sblymn lp->nsp = np; 429e124de36Sblymn } 430e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 431e124de36Sblymn newx = *x + win->ch_off; 432e124de36Sblymn if (newx < *(*lnp)->firstchp) 433e124de36Sblymn *(*lnp)->firstchp = newx; 434ee6c5161Sblymn 435e124de36Sblymn if (newx > *(*lnp)->lastchp) 436e124de36Sblymn *(*lnp)->lastchp = newx; 437e124de36Sblymn __touchline(win, *y, *x, *x); 438e124de36Sblymn return OK; 439e124de36Sblymn } 440e124de36Sblymn /* check for new line first */ 44169b405aaSblymn if (char_interp && ((*lnp)->flags & __ISPASTEOL)) { 442e124de36Sblymn *x = 0; 443e124de36Sblymn (*lnp)->flags &= ~__ISPASTEOL; 444e124de36Sblymn if (*y == win->scr_b) { 445e124de36Sblymn if (!(win->flags & __SCROLLOK)) 446e124de36Sblymn return ERR; 447e124de36Sblymn scroll(win); 448e124de36Sblymn } else { 449e124de36Sblymn (*y)++; 450e124de36Sblymn } 45143d5eb45Sroy (*lnp) = win->alines[*y]; 45243d5eb45Sroy lp = &win->alines[*y]->line[*x]; 453e124de36Sblymn } 454e124de36Sblymn /* clear out the current character */ 455f1942931Sblymn cw = (*lp).wcols; 456e124de36Sblymn if (cw >= 0) { 457e124de36Sblymn sx = *x; 458e124de36Sblymn } else { 459e124de36Sblymn for (sx = *x - 1; sx >= max(*x + cw, 0); sx--) { 460e124de36Sblymn __CTRACE(__CTRACE_INPUT, 461e124de36Sblymn "_cursesi_addwchar: clear current char (%d,%d)\n", 462e124de36Sblymn *y, sx); 46343d5eb45Sroy tp = &win->alines[*y]->line[sx]; 464301bf8ccSblymn tp->ch = win->bch; 465ee6c5161Sblymn tp->cflags = CA_BACKGROUND; 466e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 467e124de36Sblymn return ERR; 468e124de36Sblymn 469e124de36Sblymn tp->attr = win->battr; 470f1942931Sblymn tp->wcols = win->wcols; 471e124de36Sblymn } 472e124de36Sblymn sx = *x + cw; 473e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 474e124de36Sblymn newx = sx + win->ch_off; 475e124de36Sblymn if (newx < *(*lnp)->firstchp) 476e124de36Sblymn *(*lnp)->firstchp = newx; 477e124de36Sblymn } 478e124de36Sblymn 479e124de36Sblymn /* check for enough space before the end of line */ 480e124de36Sblymn cw = wcwidth(wch->vals[0]); 481452834f2Sdrochner if (cw < 0) 482452834f2Sdrochner cw = 1; 48369b405aaSblymn 484e124de36Sblymn if (cw > win->maxx - *x) { 485e124de36Sblymn __CTRACE(__CTRACE_INPUT, 486b09154d5Srin "_cursesi_addwchar: clear EOL (%d,%d)\n", *y, *x); 48773328adfSblymn if (*y == win->scr_b) { 48873328adfSblymn if (!(win->flags & __SCROLLOK)) 48973328adfSblymn return ERR; 49073328adfSblymn scroll(win); 49173328adfSblymn } 49273328adfSblymn 493e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 494e124de36Sblymn newx = *x + win->ch_off; 495e124de36Sblymn if (newx < *(*lnp)->firstchp) 496e124de36Sblymn *(*lnp)->firstchp = newx; 497ee6c5161Sblymn 498e124de36Sblymn for (tp = lp; *x < win->maxx; tp++, (*x)++) { 499301bf8ccSblymn tp->ch = win->bch; 500e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 501e124de36Sblymn return ERR; 502e124de36Sblymn tp->attr = win->battr; 503f1942931Sblymn tp->wcols = win->wcols; 504ee6c5161Sblymn tp->cflags = CA_BACKGROUND; 505e124de36Sblymn } 506e124de36Sblymn newx = win->maxx - 1 + win->ch_off; 507e124de36Sblymn if (newx > *(*lnp)->lastchp) 508e124de36Sblymn *(*lnp)->lastchp = newx; 509e124de36Sblymn __touchline(win, *y, sx, (int) win->maxx - 1); 510e124de36Sblymn sx = *x = 0; 51173328adfSblymn if (*y != win->scr_b) { 512e124de36Sblymn (*y)++; 513e124de36Sblymn } 51443d5eb45Sroy lp = &win->alines[*y]->line[0]; 51543d5eb45Sroy (*lnp) = win->alines[*y]; 516e124de36Sblymn } 517e124de36Sblymn 518e124de36Sblymn /* add spacing character */ 519e124de36Sblymn __CTRACE(__CTRACE_INPUT, 520e124de36Sblymn "_cursesi_addwchar: add character (%d,%d) 0x%x\n", 521e124de36Sblymn *y, *x, wch->vals[0]); 522e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 523e124de36Sblymn newx = *x + win->ch_off; 524e124de36Sblymn if (newx < *(*lnp)->firstchp) 525e124de36Sblymn *(*lnp)->firstchp = newx; 526ee6c5161Sblymn 527e124de36Sblymn if (lp->nsp) { 528e124de36Sblymn __cursesi_free_nsp(lp->nsp); 529e124de36Sblymn lp->nsp = NULL; 530e124de36Sblymn } 531e124de36Sblymn 532e124de36Sblymn lp->ch = wch->vals[0]; 533ee6c5161Sblymn lp->cflags &= ~ (CA_BACKGROUND | CA_CONTINUATION); 534e124de36Sblymn 535e124de36Sblymn attributes = (win->wattr | wch->attributes) 536e124de36Sblymn & (WA_ATTRIBUTES & ~__COLOR); 537e124de36Sblymn if (wch->attributes & __COLOR) 538e124de36Sblymn attributes |= wch->attributes & __COLOR; 539e124de36Sblymn else if (win->wattr & __COLOR) 540e124de36Sblymn attributes |= win->wattr & __COLOR; 541e124de36Sblymn if (attributes & __COLOR) 542e124de36Sblymn lp->attr = attributes | (win->battr & ~__COLOR); 543e124de36Sblymn else 544e124de36Sblymn lp->attr = attributes | win->battr; 545e124de36Sblymn 546f1942931Sblymn lp->wcols = cw; 547e124de36Sblymn 548e124de36Sblymn __CTRACE(__CTRACE_INPUT, 549f1942931Sblymn "_cursesi_addwchar: add spacing char 0x%x, attr 0x%x, width %d\n", 550f1942931Sblymn lp->ch, lp->attr, lp->wcols); 551e124de36Sblymn 552e124de36Sblymn if (wch->elements > 1) { 553e124de36Sblymn for (i = 1; i < wch->elements; i++) { 5548a48cf66Schristos np = malloc(sizeof(nschar_t)); 555e124de36Sblymn if (!np) 5567af2475fSrillig return ERR; 557e124de36Sblymn np->ch = wch->vals[i]; 558e124de36Sblymn np->next = lp->nsp; 559e124de36Sblymn __CTRACE(__CTRACE_INPUT, 560b09154d5Srin "_cursesi_addwchar: add non-spacing char 0x%x\n", 561b09154d5Srin np->ch); 562e124de36Sblymn lp->nsp = np; 563e124de36Sblymn } 564e124de36Sblymn } 565b09154d5Srin __CTRACE(__CTRACE_INPUT, 566b09154d5Srin "_cursesi_addwchar: non-spacing list header: %p\n", lp->nsp); 567b09154d5Srin __CTRACE(__CTRACE_INPUT, 568b09154d5Srin "_cursesi_addwchar: add rest columns (%d:%d)\n", 569e124de36Sblymn sx + 1, sx + cw - 1); 570b09154d5Srin __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: *x = %d, win->maxx = %d\n", 571b09154d5Srin *x, win->maxx); 572ee6c5161Sblymn for (tp = lp + 1, *x = sx + 1, i = cw - 1; i > 0; tp++, (*x)++, i--) { 573ee6c5161Sblymn __CTRACE(__CTRACE_INPUT, 574ee6c5161Sblymn "_cursesi_addwchar: setting continuation at x %d\n", *x); 575e124de36Sblymn if (tp->nsp) { 576e124de36Sblymn __cursesi_free_nsp(tp->nsp); 577e124de36Sblymn tp->nsp = NULL; 578e124de36Sblymn } 579e124de36Sblymn tp->ch = wch->vals[0]; 580e124de36Sblymn tp->attr = lp->attr & WA_ATTRIBUTES; 581e124de36Sblymn /* Mark as "continuation" cell */ 582a7d2c216Sblymn tp->cflags |= CA_CONTINUATION; 583ee6c5161Sblymn tp->cflags &= ~ CA_BACKGROUND; 584ee6c5161Sblymn tp->wcols = i; 585e124de36Sblymn } 58669b405aaSblymn 587f1942931Sblymn if (*x >= win->maxx) { 588652cdcd2Sblymn __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: do line wrap\n"); 58973328adfSblymn if (*y == win->scr_b) { 590b09154d5Srin __CTRACE(__CTRACE_INPUT, 591b09154d5Srin "_cursesi_addwchar: at bottom of screen\n"); 59273328adfSblymn if (!(win->flags & __SCROLLOK)) 59373328adfSblymn return ERR; 594b09154d5Srin __CTRACE(__CTRACE_INPUT, 595b09154d5Srin "_cursesi_addwchar: do a scroll\n"); 59695dcd6acSblymn if (!__NONL) 59795dcd6acSblymn *x = 0; 59873328adfSblymn scroll(win); 59973328adfSblymn } 600e124de36Sblymn newx = win->maxx - 1 + win->ch_off; 601e124de36Sblymn if (newx > *(*lnp)->lastchp) 602e124de36Sblymn *(*lnp)->lastchp = newx; 603e124de36Sblymn __touchline(win, *y, sx, (int) win->maxx - 1); 604652cdcd2Sblymn *x = sx = 0; 60573328adfSblymn if (*y != win->scr_b) { 606652cdcd2Sblymn (*y)++; 607652cdcd2Sblymn } 608652cdcd2Sblymn lp = &win->alines[*y]->line[0]; 609652cdcd2Sblymn (*lnp) = win->alines[*y]; 6107b4e98e7Sblymn *(*lnp)->lastchp = win->ch_off + win->maxx - 1; 611e124de36Sblymn } else { 612ae30211bSrillig /* clear the remaining of the current character */ 613e124de36Sblymn if (*x && *x < win->maxx) { 614e124de36Sblymn ex = sx + cw; 61543d5eb45Sroy tp = &win->alines[*y]->line[ex]; 616f1942931Sblymn while (ex < win->maxx && tp->wcols < 0) { 617e124de36Sblymn __CTRACE(__CTRACE_INPUT, 618e124de36Sblymn "_cursesi_addwchar: clear " 619e124de36Sblymn "remaining of current char (%d,%d)nn", 620e124de36Sblymn *y, ex); 621301bf8ccSblymn tp->ch = win->bch; 622ee6c5161Sblymn tp->cflags = CA_BACKGROUND; 623e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 624e124de36Sblymn return ERR; 625e124de36Sblymn tp->attr = win->battr; 626f1942931Sblymn tp->wcols = win->wcols; 627e124de36Sblymn tp++, ex++; 628e124de36Sblymn } 629e124de36Sblymn newx = ex - 1 + win->ch_off; 630e124de36Sblymn if (newx > *(*lnp)->lastchp) 631e124de36Sblymn *(*lnp)->lastchp = newx; 632e124de36Sblymn __touchline(win, *y, sx, ex - 1); 633e124de36Sblymn } 634e124de36Sblymn } 635e124de36Sblymn 636b09154d5Srin __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: %d : 0x%x\n", 637b09154d5Srin lp->ch, lp->attr); 638b09154d5Srin __CTRACE(__CTRACE_INPUT, 639b09154d5Srin "_cursesi_addwchar: *x = %d, *y = %d, win->maxx = %d\n", 640b09154d5Srin *x, *y, win->maxx); 6411369811dSroy __sync(win); 642e124de36Sblymn return OK; 643e124de36Sblymn #endif 644e124de36Sblymn } 645