1*452834f2Sdrochner /* $NetBSD: addbytes.c,v 1.36 2010/02/23 19:48:26 drochner 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*452834f2Sdrochner __RCSID("$NetBSD: addbytes.c,v 1.36 2010/02/23 19:48:26 drochner Exp $"); 38716747aaSmikel #endif 3961f28255Scgd #endif /* not lint */ 4061f28255Scgd 41e124de36Sblymn #include <stdlib.h> 42d29088daScgd #include "curses.h" 4323464ee5Sblymn #include "curses_private.h" 448d259104Sblymn #ifdef DEBUG 458d259104Sblymn #include <assert.h> 468d259104Sblymn #endif 4761f28255Scgd 48019bbd13Scgd #define SYNCH_IN {y = win->cury; x = win->curx;} 49019bbd13Scgd #define SYNCH_OUT {win->cury = y; win->curx = x;} 50e124de36Sblymn #define PSYNCH_IN {*y = win->cury; *x = win->curx;} 51e124de36Sblymn #define PSYNCH_OUT {win->cury = *y; win->curx = *x;} 5275de25bbSalm 53aaf74682Sblymn #ifndef _CURSES_USE_MACROS 54aaf74682Sblymn 55aaf74682Sblymn /* 56aaf74682Sblymn * addbytes -- 57aaf74682Sblymn * Add the character to the current position in stdscr. 58aaf74682Sblymn */ 59aaf74682Sblymn int 60aaf74682Sblymn addbytes(const char *bytes, int count) 61aaf74682Sblymn { 62aaf74682Sblymn return __waddbytes(stdscr, bytes, count, 0); 63aaf74682Sblymn } 64aaf74682Sblymn 6561f28255Scgd /* 6662a3457dSmycroft * waddbytes -- 6762a3457dSmycroft * Add the character to the current position in the given window. 6861f28255Scgd */ 6962a3457dSmycroft int 70aaf74682Sblymn waddbytes(WINDOW *win, const char *bytes, int count) 71aaf74682Sblymn { 72aaf74682Sblymn return __waddbytes(win, bytes, count, 0); 73aaf74682Sblymn } 74aaf74682Sblymn 75aaf74682Sblymn /* 76aaf74682Sblymn * mvaddbytes -- 77aaf74682Sblymn * Add the characters to stdscr at the location given. 78aaf74682Sblymn */ 79aaf74682Sblymn int 80aaf74682Sblymn mvaddbytes(int y, int x, const char *bytes, int count) 81aaf74682Sblymn { 82aaf74682Sblymn return mvwaddbytes(stdscr, y, x, bytes, count); 83aaf74682Sblymn } 84aaf74682Sblymn 85aaf74682Sblymn /* 86aaf74682Sblymn * mvwaddbytes -- 87aaf74682Sblymn * Add the characters to the given window at the location given. 88aaf74682Sblymn */ 89aaf74682Sblymn int 90aaf74682Sblymn mvwaddbytes(WINDOW *win, int y, int x, const char *bytes, int count) 91aaf74682Sblymn { 92aaf74682Sblymn if (wmove(win, y, x) == ERR) 93aaf74682Sblymn return ERR; 94aaf74682Sblymn 95aaf74682Sblymn return __waddbytes(win, bytes, count, 0); 96aaf74682Sblymn } 97aaf74682Sblymn 98aaf74682Sblymn #endif 99aaf74682Sblymn 100aaf74682Sblymn /* 101aaf74682Sblymn * waddbytes -- 102aaf74682Sblymn * Add the character to the current position in the given window. 103aaf74682Sblymn */ 104aaf74682Sblymn int 105aaf74682Sblymn __waddbytes(WINDOW *win, const char *bytes, int count, attr_t attr) 10661f28255Scgd { 107e124de36Sblymn int x, y, err; 108019bbd13Scgd __LINE *lp; 109e124de36Sblymn #ifdef HAVE_WCHAR 110e124de36Sblymn int n; 111e124de36Sblymn cchar_t cc; 112e124de36Sblymn wchar_t wc; 113c71a9f1dStnozaki mbstate_t st; 114e124de36Sblymn #else 115e124de36Sblymn int c; 116e124de36Sblymn #endif 1178d259104Sblymn #ifdef DEBUG 1188d259104Sblymn int i; 1198d259104Sblymn 1208d259104Sblymn for (i = 0; i < win->maxy; i++) { 12143d5eb45Sroy assert(win->alines[i]->sentinel == SENTINEL_VALUE); 1228d259104Sblymn } 123e124de36Sblymn 124e124de36Sblymn __CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count); 1258d259104Sblymn #endif 12661f28255Scgd 127e124de36Sblymn err = OK; 12862a3457dSmycroft SYNCH_IN; 12943d5eb45Sroy lp = win->alines[y]; 13062a3457dSmycroft 131c71a9f1dStnozaki #ifdef HAVE_WCHAR 132c71a9f1dStnozaki (void)mbrtowc(NULL, NULL, (size_t)0, &st); 133c71a9f1dStnozaki #endif 134e124de36Sblymn while (count > 0) { 135e124de36Sblymn #ifndef HAVE_WCHAR 136716747aaSmikel c = *bytes++; 13762a3457dSmycroft #ifdef DEBUG 1381f221324Sjdc __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n", 1391f221324Sjdc c, attr, y, x); 14062a3457dSmycroft #endif 141e124de36Sblymn err = _cursesi_addbyte(win, &lp, &y, &x, c, attr); 142e124de36Sblymn count--; 143e124de36Sblymn #else 144e124de36Sblymn /* 145e124de36Sblymn * For wide character support only, try and convert the 146e124de36Sblymn * given string into a wide character - we do this because 147e124de36Sblymn * this is how ncurses behaves (not that I think this is 148e124de36Sblymn * actually the correct thing to do but if we don't do it 149e124de36Sblymn * a lot of things that rely on this behaviour will break 150e124de36Sblymn * and we will be blamed). If the conversion succeeds 151e124de36Sblymn * then we eat the n characters used to make the wide char 152e124de36Sblymn * from the string. 153e124de36Sblymn */ 154c71a9f1dStnozaki n = (int)mbrtowc(&wc, bytes, (size_t)count, &st); 155c71a9f1dStnozaki if (n < 0) { 156c71a9f1dStnozaki /* not a valid conversion just eat a char */ 157e124de36Sblymn wc = *bytes; 158e124de36Sblymn n = 1; 159c71a9f1dStnozaki (void)mbrtowc(NULL, NULL, (size_t)0, &st); 160c71a9f1dStnozaki } else if (wc == 0) { 161c71a9f1dStnozaki break; 162e124de36Sblymn } 163e124de36Sblymn #ifdef DEBUG 164e124de36Sblymn __CTRACE(__CTRACE_INPUT, 165e124de36Sblymn "ADDBYTES WIDE(0x%x [%s], %x) at (%d, %d), ate %d bytes\n", 166e124de36Sblymn (unsigned) wc, unctrl((unsigned) wc), attr, y, x, n); 167e124de36Sblymn #endif 168e124de36Sblymn cc.vals[0] = wc; 169e124de36Sblymn cc.elements = 1; 170e124de36Sblymn cc.attributes = attr; 171e124de36Sblymn err = _cursesi_addwchar(win, &lp, &y, &x, &cc); 172e124de36Sblymn bytes += n; 173e124de36Sblymn count -= n; 174e124de36Sblymn #endif 175e124de36Sblymn } 176e124de36Sblymn 177e124de36Sblymn SYNCH_OUT; 178e124de36Sblymn 179e124de36Sblymn #ifdef DEBUG 180e124de36Sblymn for (i = 0; i < win->maxy; i++) { 18143d5eb45Sroy assert(win->alines[i]->sentinel == SENTINEL_VALUE); 182e124de36Sblymn } 183e124de36Sblymn #endif 184e124de36Sblymn 185e124de36Sblymn return (err); 186e124de36Sblymn } 187e124de36Sblymn 188e124de36Sblymn /* 189e124de36Sblymn * _cursesi_addbyte - 190e124de36Sblymn * Internal function to add a byte and update the row and column 191e124de36Sblymn * positions as appropriate. This function is only used in the narrow 192e124de36Sblymn * character version of curses. 193e124de36Sblymn */ 194e124de36Sblymn int 195e124de36Sblymn _cursesi_addbyte(WINDOW *win, __LINE **lp, int *y, int *x, int c, 196e124de36Sblymn attr_t attr) 197e124de36Sblymn { 198e124de36Sblymn static char blanks[] = " "; 199e124de36Sblymn int newx; 200e124de36Sblymn attr_t attributes; 201e124de36Sblymn 20261f28255Scgd switch (c) { 20361f28255Scgd case '\t': 204e124de36Sblymn PSYNCH_OUT; 205e124de36Sblymn if (waddbytes(win, blanks, 8 - (*x % 8)) == ERR) 20662a3457dSmycroft return (ERR); 207e124de36Sblymn PSYNCH_IN; 20861f28255Scgd break; 20961f28255Scgd 21061f28255Scgd default: 21162a3457dSmycroft #ifdef DEBUG 2121f221324Sjdc __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", 213e124de36Sblymn win, *y, *x); 21461f28255Scgd #endif 215019bbd13Scgd 216e124de36Sblymn if ((*lp)->flags & __ISPASTEOL) { 21743d5eb45Sroy new_line: 218e124de36Sblymn *x = 0; 219e124de36Sblymn (*lp)->flags &= ~__ISPASTEOL; 220e124de36Sblymn if (*y == win->scr_b) { 2213f9388e3Sjdc #ifdef DEBUG 2221f221324Sjdc __CTRACE(__CTRACE_INPUT, 2231f221324Sjdc "ADDBYTES - on bottom " 224c841017dSdsl "of scrolling region\n"); 2253f9388e3Sjdc #endif 226c841017dSdsl if (!(win->flags & __SCROLLOK)) 227c841017dSdsl return ERR; 228e124de36Sblymn PSYNCH_OUT; 22961f28255Scgd scroll(win); 230e124de36Sblymn PSYNCH_IN; 231019bbd13Scgd } else { 232e124de36Sblymn (*y)++; 233019bbd13Scgd } 23443d5eb45Sroy *lp = win->alines[*y]; 235019bbd13Scgd if (c == '\n') 236019bbd13Scgd break; 237019bbd13Scgd } 238019bbd13Scgd 23940add0b9Smycroft attributes = (win->wattr | attr) & 24040add0b9Smycroft (__ATTRIBUTES & ~__COLOR); 24140b39f92Sjdc if (attr & __COLOR) 24240b39f92Sjdc attributes |= attr & __COLOR; 24340b39f92Sjdc else if (win->wattr & __COLOR) 24440b39f92Sjdc attributes |= win->wattr & __COLOR; 24562a3457dSmycroft #ifdef DEBUG 2461f221324Sjdc __CTRACE(__CTRACE_INPUT, 2471f221324Sjdc "ADDBYTES: 1: y = %d, x = %d, firstch = %d, " 248c841017dSdsl "lastch = %d\n", 24943d5eb45Sroy *y, *x, *win->alines[*y]->firstchp, 25043d5eb45Sroy *win->alines[*y]->lastchp); 251019bbd13Scgd #endif 25202559eb6Sjdc /* 25302559eb6Sjdc * Always update the change pointers. Otherwise, 25402559eb6Sjdc * we could end up not displaying 'blank' characters 25502559eb6Sjdc * when overlapping windows are displayed. 25602559eb6Sjdc */ 257e124de36Sblymn newx = *x + win->ch_off; 258e124de36Sblymn (*lp)->flags |= __ISDIRTY; 2598e3f5589Sjdc /* 2608e3f5589Sjdc * firstchp/lastchp are shared between 2618e3f5589Sjdc * parent window and sub-window. 2628e3f5589Sjdc */ 263e124de36Sblymn if (newx < *(*lp)->firstchp) 264e124de36Sblymn *(*lp)->firstchp = newx; 265e124de36Sblymn if (newx > *(*lp)->lastchp) 266e124de36Sblymn *(*lp)->lastchp = newx; 267019bbd13Scgd #ifdef DEBUG 2681f221324Sjdc __CTRACE(__CTRACE_INPUT, 2691f221324Sjdc "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", 270e124de36Sblymn *(*lp)->firstchp, *(*lp)->lastchp, 271e124de36Sblymn *(*lp)->firstchp - win->ch_off, 272e124de36Sblymn *(*lp)->lastchp - win->ch_off); 273019bbd13Scgd #endif 274978ab4adSjdc if (win->bch != ' ' && c == ' ') 275e124de36Sblymn (*lp)->line[*x].ch = win->bch; 276978ab4adSjdc else 277e124de36Sblymn (*lp)->line[*x].ch = c; 278e124de36Sblymn 279978ab4adSjdc if (attributes & __COLOR) 280e124de36Sblymn (*lp)->line[*x].attr = 281978ab4adSjdc attributes | (win->battr & ~__COLOR); 282978ab4adSjdc else 283e124de36Sblymn (*lp)->line[*x].attr = attributes | win->battr; 284e124de36Sblymn 285e124de36Sblymn if (*x == win->maxx - 1) 286e124de36Sblymn (*lp)->flags |= __ISPASTEOL; 287019bbd13Scgd else 288e124de36Sblymn (*x)++; 289019bbd13Scgd #ifdef DEBUG 2901f221324Sjdc __CTRACE(__CTRACE_INPUT, 2911f221324Sjdc "ADDBYTES: 2: y = %d, x = %d, firstch = %d, " 2921f221324Sjdc "lastch = %d\n", 29343d5eb45Sroy *y, *x, *win->alines[*y]->firstchp, 29443d5eb45Sroy *win->alines[*y]->lastchp); 29561f28255Scgd #endif 29661f28255Scgd break; 29761f28255Scgd case '\n': 298e124de36Sblymn PSYNCH_OUT; 29961f28255Scgd wclrtoeol(win); 300e124de36Sblymn PSYNCH_IN; 30143d5eb45Sroy goto new_line; 30261f28255Scgd case '\r': 303e124de36Sblymn *x = 0; 304e124de36Sblymn break; 30561f28255Scgd case '\b': 306e124de36Sblymn if (--(*x) < 0) 307e124de36Sblymn *x = 0; 30861f28255Scgd break; 30961f28255Scgd } 3108d259104Sblymn 31162a3457dSmycroft return (OK); 31261f28255Scgd } 313e124de36Sblymn 314e124de36Sblymn /* 315e124de36Sblymn * _cursesi_addwchar - 316e124de36Sblymn * Internal function to add a wide character and update the row 317e124de36Sblymn * and column positions. 318e124de36Sblymn */ 319e124de36Sblymn int 320e124de36Sblymn _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x, 321e124de36Sblymn const cchar_t *wch) 322e124de36Sblymn { 323e124de36Sblymn #ifndef HAVE_WCHAR 324e124de36Sblymn return (ERR); 325e124de36Sblymn #else 326e124de36Sblymn int sx = 0, ex = 0, cw = 0, i = 0, newx = 0; 32743d5eb45Sroy __LDATA *lp = &win->alines[*y]->line[*x], *tp = NULL; 328e124de36Sblymn nschar_t *np = NULL; 329e124de36Sblymn cchar_t cc; 330e124de36Sblymn attr_t attributes; 331e124de36Sblymn 332e124de36Sblymn /* special characters handling */ 333e124de36Sblymn switch (wch->vals[0]) { 334e124de36Sblymn case L'\b': 335e124de36Sblymn if (--*x < 0) 336e124de36Sblymn *x = 0; 337e124de36Sblymn win->curx = *x; 338e124de36Sblymn return OK; 339e124de36Sblymn case L'\r': 340194f45e1Sjdc *x = 0; 341e124de36Sblymn return OK; 342e124de36Sblymn case L'\n': 343e124de36Sblymn wclrtoeol(win); 344e124de36Sblymn PSYNCH_IN; 345e124de36Sblymn *x = 0; 346e124de36Sblymn (*lnp)->flags &= ~__ISPASTEOL; 347e124de36Sblymn if (*y == win->scr_b) { 348e124de36Sblymn if (!(win->flags & __SCROLLOK)) 349e124de36Sblymn return ERR; 350e124de36Sblymn PSYNCH_OUT; 351e124de36Sblymn scroll(win); 352e124de36Sblymn PSYNCH_IN; 353e124de36Sblymn } else { 354e124de36Sblymn (*y)++; 355e124de36Sblymn } 356e124de36Sblymn PSYNCH_OUT; 357e124de36Sblymn return OK; 358e124de36Sblymn case L'\t': 359e124de36Sblymn cc.vals[0] = L' '; 360e124de36Sblymn cc.elements = 1; 361e124de36Sblymn cc.attributes = win->wattr; 362e124de36Sblymn for (i = 0; i < 8 - (*x % 8); i++) { 363e124de36Sblymn if (wadd_wch(win, &cc) == ERR) 364e124de36Sblymn return ERR; 365e124de36Sblymn } 366e124de36Sblymn return OK; 367e124de36Sblymn } 368e124de36Sblymn 369e124de36Sblymn /* check for non-spacing character */ 370e124de36Sblymn if (!wcwidth(wch->vals[0])) { 371e124de36Sblymn #ifdef DEBUG 372e124de36Sblymn __CTRACE(__CTRACE_INPUT, 373e124de36Sblymn "_cursesi_addwchar: char '%c' is non-spacing\n", 374e124de36Sblymn wch->vals[0]); 375e124de36Sblymn #endif /* DEBUG */ 376e124de36Sblymn cw = WCOL(*lp); 377e124de36Sblymn if (cw < 0) { 378e124de36Sblymn lp += cw; 379e124de36Sblymn *x += cw; 380e124de36Sblymn } 381e124de36Sblymn for (i = 0; i < wch->elements; i++) { 382e124de36Sblymn if (!(np = (nschar_t *) malloc(sizeof(nschar_t)))) 383e124de36Sblymn return ERR;; 384e124de36Sblymn np->ch = wch->vals[i]; 385e124de36Sblymn np->next = lp->nsp; 386e124de36Sblymn lp->nsp = np; 387e124de36Sblymn } 388e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 389e124de36Sblymn newx = *x + win->ch_off; 390e124de36Sblymn if (newx < *(*lnp)->firstchp) 391e124de36Sblymn *(*lnp)->firstchp = newx; 392e124de36Sblymn if (newx > *(*lnp)->lastchp) 393e124de36Sblymn *(*lnp)->lastchp = newx; 394e124de36Sblymn __touchline(win, *y, *x, *x); 395e124de36Sblymn return OK; 396e124de36Sblymn } 397e124de36Sblymn /* check for new line first */ 398e124de36Sblymn if ((*lnp)->flags & __ISPASTEOL) { 399e124de36Sblymn *x = 0; 400e124de36Sblymn (*lnp)->flags &= ~__ISPASTEOL; 401e124de36Sblymn if (*y == win->scr_b) { 402e124de36Sblymn if (!(win->flags & __SCROLLOK)) 403e124de36Sblymn return ERR; 404e124de36Sblymn PSYNCH_OUT; 405e124de36Sblymn scroll(win); 406e124de36Sblymn PSYNCH_IN; 407e124de36Sblymn } else { 408e124de36Sblymn (*y)++; 409e124de36Sblymn } 41043d5eb45Sroy (*lnp) = win->alines[*y]; 41143d5eb45Sroy lp = &win->alines[*y]->line[*x]; 412e124de36Sblymn } 413e124de36Sblymn /* clear out the current character */ 414e124de36Sblymn cw = WCOL(*lp); 415e124de36Sblymn if (cw >= 0) { 416e124de36Sblymn sx = *x; 417e124de36Sblymn } else { 418e124de36Sblymn for (sx = *x - 1; sx >= max(*x + cw, 0); sx--) { 419e124de36Sblymn #ifdef DEBUG 420e124de36Sblymn __CTRACE(__CTRACE_INPUT, 421e124de36Sblymn "_cursesi_addwchar: clear current char (%d,%d)\n", 422e124de36Sblymn *y, sx); 423e124de36Sblymn #endif /* DEBUG */ 42443d5eb45Sroy tp = &win->alines[*y]->line[sx]; 425e124de36Sblymn tp->ch = (wchar_t) btowc((int) win->bch); 426e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 427e124de36Sblymn return ERR; 428e124de36Sblymn 429e124de36Sblymn tp->attr = win->battr; 430e124de36Sblymn SET_WCOL(*tp, 1); 431e124de36Sblymn } 432e124de36Sblymn sx = *x + cw; 433e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 434e124de36Sblymn newx = sx + win->ch_off; 435e124de36Sblymn if (newx < *(*lnp)->firstchp) 436e124de36Sblymn *(*lnp)->firstchp = newx; 437e124de36Sblymn } 438e124de36Sblymn 439e124de36Sblymn /* check for enough space before the end of line */ 440e124de36Sblymn cw = wcwidth(wch->vals[0]); 441*452834f2Sdrochner if (cw < 0) 442*452834f2Sdrochner cw = 1; 443e124de36Sblymn if (cw > win->maxx - *x) { 444e124de36Sblymn #ifdef DEBUG 445e124de36Sblymn __CTRACE(__CTRACE_INPUT, 446e124de36Sblymn "_cursesi_addwchar: clear EOL (%d,%d)\n", 447e124de36Sblymn *y, *x); 448e124de36Sblymn #endif /* DEBUG */ 449e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 450e124de36Sblymn newx = *x + win->ch_off; 451e124de36Sblymn if (newx < *(*lnp)->firstchp) 452e124de36Sblymn *(*lnp)->firstchp = newx; 453e124de36Sblymn for (tp = lp; *x < win->maxx; tp++, (*x)++) { 454e124de36Sblymn tp->ch = (wchar_t) btowc((int) win->bch); 455e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 456e124de36Sblymn return ERR; 457e124de36Sblymn tp->attr = win->battr; 458e124de36Sblymn SET_WCOL(*tp, 1); 459e124de36Sblymn } 460e124de36Sblymn newx = win->maxx - 1 + win->ch_off; 461e124de36Sblymn if (newx > *(*lnp)->lastchp) 462e124de36Sblymn *(*lnp)->lastchp = newx; 463e124de36Sblymn __touchline(win, *y, sx, (int) win->maxx - 1); 464e124de36Sblymn sx = *x = 0; 465e124de36Sblymn if (*y == win->scr_b) { 466e124de36Sblymn if (!(win->flags & __SCROLLOK)) 467e124de36Sblymn return ERR; 468e124de36Sblymn PSYNCH_OUT; 469e124de36Sblymn scroll(win); 470e124de36Sblymn PSYNCH_IN; 471e124de36Sblymn } else { 472e124de36Sblymn (*y)++; 473e124de36Sblymn } 47443d5eb45Sroy lp = &win->alines[*y]->line[0]; 47543d5eb45Sroy (*lnp) = win->alines[*y]; 476e124de36Sblymn } 477e124de36Sblymn win->cury = *y; 478e124de36Sblymn 479e124de36Sblymn /* add spacing character */ 480e124de36Sblymn #ifdef DEBUG 481e124de36Sblymn __CTRACE(__CTRACE_INPUT, 482e124de36Sblymn "_cursesi_addwchar: add character (%d,%d) 0x%x\n", 483e124de36Sblymn *y, *x, wch->vals[0]); 484e124de36Sblymn #endif /* DEBUG */ 485e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 486e124de36Sblymn newx = *x + win->ch_off; 487e124de36Sblymn if (newx < *(*lnp)->firstchp) 488e124de36Sblymn *(*lnp)->firstchp = newx; 489e124de36Sblymn if (lp->nsp) { 490e124de36Sblymn __cursesi_free_nsp(lp->nsp); 491e124de36Sblymn lp->nsp = NULL; 492e124de36Sblymn } 493e124de36Sblymn 494e124de36Sblymn lp->ch = wch->vals[0]; 495e124de36Sblymn 496e124de36Sblymn attributes = (win->wattr | wch->attributes) 497e124de36Sblymn & (WA_ATTRIBUTES & ~__COLOR); 498e124de36Sblymn if (wch->attributes & __COLOR) 499e124de36Sblymn attributes |= wch->attributes & __COLOR; 500e124de36Sblymn else if (win->wattr & __COLOR) 501e124de36Sblymn attributes |= win->wattr & __COLOR; 502e124de36Sblymn if (attributes & __COLOR) 503e124de36Sblymn lp->attr = attributes | (win->battr & ~__COLOR); 504e124de36Sblymn else 505e124de36Sblymn lp->attr = attributes | win->battr; 506e124de36Sblymn 507e124de36Sblymn SET_WCOL(*lp, cw); 508e124de36Sblymn 509e124de36Sblymn #ifdef DEBUG 510e124de36Sblymn __CTRACE(__CTRACE_INPUT, 511e124de36Sblymn "_cursesi_addwchar: add spacing char 0x%x, attr 0x%x\n", 512e124de36Sblymn lp->ch, lp->attr); 513e124de36Sblymn #endif /* DEBUG */ 514e124de36Sblymn 515e124de36Sblymn if (wch->elements > 1) { 516e124de36Sblymn for (i = 1; i < wch->elements; i++) { 517e124de36Sblymn np = (nschar_t *)malloc(sizeof(nschar_t)); 518e124de36Sblymn if (!np) 519e124de36Sblymn return ERR;; 520e124de36Sblymn np->ch = wch->vals[i]; 521e124de36Sblymn np->next = lp->nsp; 522e124de36Sblymn #ifdef DEBUG 523e124de36Sblymn __CTRACE(__CTRACE_INPUT, 524e124de36Sblymn "_cursesi_addwchar: add non-spacing char 0x%x\n", np->ch); 525e124de36Sblymn #endif /* DEBUG */ 526e124de36Sblymn lp->nsp = np; 527e124de36Sblymn } 528e124de36Sblymn } 529e124de36Sblymn #ifdef DEBUG 530e124de36Sblymn __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: non-spacing list header: %p\n", 531e124de36Sblymn lp->nsp); 532e124de36Sblymn __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: add rest columns (%d:%d)\n", 533e124de36Sblymn sx + 1, sx + cw - 1); 534e124de36Sblymn #endif /* DEBUG */ 535e124de36Sblymn for (tp = lp + 1, *x = sx + 1; *x - sx <= cw - 1; tp++, (*x)++) { 536e124de36Sblymn if (tp->nsp) { 537e124de36Sblymn __cursesi_free_nsp(tp->nsp); 538e124de36Sblymn tp->nsp = NULL; 539e124de36Sblymn } 540e124de36Sblymn tp->ch = wch->vals[0]; 541e124de36Sblymn tp->attr = lp->attr & WA_ATTRIBUTES; 542e124de36Sblymn /* Mark as "continuation" cell */ 543e124de36Sblymn tp->attr |= __WCWIDTH; 544e124de36Sblymn } 545e124de36Sblymn if (*x == win->maxx) { 546e124de36Sblymn (*lnp)->flags |= __ISPASTEOL; 547e124de36Sblymn newx = win->maxx - 1 + win->ch_off; 548e124de36Sblymn if (newx > *(*lnp)->lastchp) 549e124de36Sblymn *(*lnp)->lastchp = newx; 550e124de36Sblymn __touchline(win, *y, sx, (int) win->maxx - 1); 551e124de36Sblymn win->curx = sx; 552e124de36Sblymn } else { 553e124de36Sblymn win->curx = *x; 554e124de36Sblymn 555e124de36Sblymn /* clear the remining of the current characer */ 556e124de36Sblymn if (*x && *x < win->maxx) { 557e124de36Sblymn ex = sx + cw; 55843d5eb45Sroy tp = &win->alines[*y]->line[ex]; 559e124de36Sblymn while (ex < win->maxx && WCOL(*tp) < 0) { 560e124de36Sblymn #ifdef DEBUG 561e124de36Sblymn __CTRACE(__CTRACE_INPUT, 562e124de36Sblymn "_cursesi_addwchar: clear " 563e124de36Sblymn "remaining of current char (%d,%d)nn", 564e124de36Sblymn *y, ex); 565e124de36Sblymn #endif /* DEBUG */ 566e124de36Sblymn tp->ch = (wchar_t) btowc((int) win->bch); 567e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 568e124de36Sblymn return ERR; 569e124de36Sblymn tp->attr = win->battr; 570e124de36Sblymn SET_WCOL(*tp, 1); 571e124de36Sblymn tp++, ex++; 572e124de36Sblymn } 573e124de36Sblymn newx = ex - 1 + win->ch_off; 574e124de36Sblymn if (newx > *(*lnp)->lastchp) 575e124de36Sblymn *(*lnp)->lastchp = newx; 576e124de36Sblymn __touchline(win, *y, sx, ex - 1); 577e124de36Sblymn } 578e124de36Sblymn } 579e124de36Sblymn 580e124de36Sblymn #ifdef DEBUG 581e124de36Sblymn __CTRACE(__CTRACE_INPUT, "add_wch: %d : 0x%x\n", lp->ch, lp->attr); 582e124de36Sblymn #endif /* DEBUG */ 583e124de36Sblymn return OK; 584e124de36Sblymn #endif 585e124de36Sblymn } 586