1*e124de36Sblymn /* $NetBSD: addbytes.c,v 1.32 2007/05/28 15:01:53 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*e124de36Sblymn __RCSID("$NetBSD: addbytes.c,v 1.32 2007/05/28 15:01:53 blymn Exp $"); 38716747aaSmikel #endif 3961f28255Scgd #endif /* not lint */ 4061f28255Scgd 41*e124de36Sblymn #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;} 50*e124de36Sblymn #define PSYNCH_IN {*y = win->cury; *x = win->curx;} 51*e124de36Sblymn #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 { 107*e124de36Sblymn int x, y, err; 108019bbd13Scgd __LINE *lp; 109*e124de36Sblymn #ifdef HAVE_WCHAR 110*e124de36Sblymn int n; 111*e124de36Sblymn cchar_t cc; 112*e124de36Sblymn wchar_t wc; 113*e124de36Sblymn #else 114*e124de36Sblymn int c; 115*e124de36Sblymn #endif 1168d259104Sblymn #ifdef DEBUG 1178d259104Sblymn int i; 1188d259104Sblymn 1198d259104Sblymn for (i = 0; i < win->maxy; i++) { 1208d259104Sblymn assert(win->lines[i]->sentinel == SENTINEL_VALUE); 1218d259104Sblymn } 122*e124de36Sblymn 123*e124de36Sblymn __CTRACE(__CTRACE_INPUT, "ADDBYTES: add %d bytes\n", count); 1248d259104Sblymn #endif 12561f28255Scgd 126*e124de36Sblymn err = OK; 12762a3457dSmycroft SYNCH_IN; 1288d259104Sblymn lp = win->lines[y]; 12962a3457dSmycroft 130*e124de36Sblymn while (count > 0) { 131*e124de36Sblymn #ifndef HAVE_WCHAR 132716747aaSmikel c = *bytes++; 13362a3457dSmycroft #ifdef DEBUG 1341f221324Sjdc __CTRACE(__CTRACE_INPUT, "ADDBYTES('%c', %x) at (%d, %d)\n", 1351f221324Sjdc c, attr, y, x); 13662a3457dSmycroft #endif 137*e124de36Sblymn err = _cursesi_addbyte(win, &lp, &y, &x, c, attr); 138*e124de36Sblymn count--; 139*e124de36Sblymn #else 140*e124de36Sblymn /* 141*e124de36Sblymn * For wide character support only, try and convert the 142*e124de36Sblymn * given string into a wide character - we do this because 143*e124de36Sblymn * this is how ncurses behaves (not that I think this is 144*e124de36Sblymn * actually the correct thing to do but if we don't do it 145*e124de36Sblymn * a lot of things that rely on this behaviour will break 146*e124de36Sblymn * and we will be blamed). If the conversion succeeds 147*e124de36Sblymn * then we eat the n characters used to make the wide char 148*e124de36Sblymn * from the string. 149*e124de36Sblymn */ 150*e124de36Sblymn n = mbtowc(&wc, bytes, count); 151*e124de36Sblymn if (n == 0) 152*e124de36Sblymn break; 153*e124de36Sblymn else if (n < 0) { /* not a valid conversion just eat a char */ 154*e124de36Sblymn wc = *bytes; 155*e124de36Sblymn n = 1; 156*e124de36Sblymn } 157*e124de36Sblymn 158*e124de36Sblymn 159*e124de36Sblymn #ifdef DEBUG 160*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 161*e124de36Sblymn "ADDBYTES WIDE(0x%x [%s], %x) at (%d, %d), ate %d bytes\n", 162*e124de36Sblymn (unsigned) wc, unctrl((unsigned) wc), attr, y, x, n); 163*e124de36Sblymn #endif 164*e124de36Sblymn cc.vals[0] = wc; 165*e124de36Sblymn cc.elements = 1; 166*e124de36Sblymn cc.attributes = attr; 167*e124de36Sblymn err = _cursesi_addwchar(win, &lp, &y, &x, &cc); 168*e124de36Sblymn bytes += n; 169*e124de36Sblymn count -= n; 170*e124de36Sblymn #endif 171*e124de36Sblymn } 172*e124de36Sblymn 173*e124de36Sblymn SYNCH_OUT; 174*e124de36Sblymn 175*e124de36Sblymn #ifdef DEBUG 176*e124de36Sblymn for (i = 0; i < win->maxy; i++) { 177*e124de36Sblymn assert(win->lines[i]->sentinel == SENTINEL_VALUE); 178*e124de36Sblymn } 179*e124de36Sblymn #endif 180*e124de36Sblymn 181*e124de36Sblymn return (err); 182*e124de36Sblymn } 183*e124de36Sblymn 184*e124de36Sblymn /* 185*e124de36Sblymn * _cursesi_addbyte - 186*e124de36Sblymn * Internal function to add a byte and update the row and column 187*e124de36Sblymn * positions as appropriate. This function is only used in the narrow 188*e124de36Sblymn * character version of curses. 189*e124de36Sblymn */ 190*e124de36Sblymn int 191*e124de36Sblymn _cursesi_addbyte(WINDOW *win, __LINE **lp, int *y, int *x, int c, 192*e124de36Sblymn attr_t attr) 193*e124de36Sblymn { 194*e124de36Sblymn static char blanks[] = " "; 195*e124de36Sblymn int newx; 196*e124de36Sblymn attr_t attributes; 197*e124de36Sblymn 19861f28255Scgd switch (c) { 19961f28255Scgd case '\t': 200*e124de36Sblymn PSYNCH_OUT; 201*e124de36Sblymn if (waddbytes(win, blanks, 8 - (*x % 8)) == ERR) 20262a3457dSmycroft return (ERR); 203*e124de36Sblymn PSYNCH_IN; 20461f28255Scgd break; 20561f28255Scgd 20661f28255Scgd default: 20762a3457dSmycroft #ifdef DEBUG 2081f221324Sjdc __CTRACE(__CTRACE_INPUT, "ADDBYTES(%p, %d, %d)\n", 209*e124de36Sblymn win, *y, *x); 21061f28255Scgd #endif 211019bbd13Scgd 212*e124de36Sblymn if ((*lp)->flags & __ISPASTEOL) { 213c7ba2828Sdsl newline: 214*e124de36Sblymn *x = 0; 215*e124de36Sblymn (*lp)->flags &= ~__ISPASTEOL; 216*e124de36Sblymn if (*y == win->scr_b) { 2173f9388e3Sjdc #ifdef DEBUG 2181f221324Sjdc __CTRACE(__CTRACE_INPUT, 2191f221324Sjdc "ADDBYTES - on bottom " 220c841017dSdsl "of scrolling region\n"); 2213f9388e3Sjdc #endif 222c841017dSdsl if (!(win->flags & __SCROLLOK)) 223c841017dSdsl return ERR; 224*e124de36Sblymn PSYNCH_OUT; 22561f28255Scgd scroll(win); 226*e124de36Sblymn PSYNCH_IN; 227019bbd13Scgd } else { 228*e124de36Sblymn (*y)++; 229019bbd13Scgd } 230*e124de36Sblymn *lp = win->lines[*y]; 231019bbd13Scgd if (c == '\n') 232019bbd13Scgd break; 233019bbd13Scgd } 234019bbd13Scgd 23540add0b9Smycroft attributes = (win->wattr | attr) & 23640add0b9Smycroft (__ATTRIBUTES & ~__COLOR); 23740b39f92Sjdc if (attr & __COLOR) 23840b39f92Sjdc attributes |= attr & __COLOR; 23940b39f92Sjdc else if (win->wattr & __COLOR) 24040b39f92Sjdc attributes |= win->wattr & __COLOR; 24162a3457dSmycroft #ifdef DEBUG 2421f221324Sjdc __CTRACE(__CTRACE_INPUT, 2431f221324Sjdc "ADDBYTES: 1: y = %d, x = %d, firstch = %d, " 244c841017dSdsl "lastch = %d\n", 245*e124de36Sblymn *y, *x, *win->lines[*y]->firstchp, 246*e124de36Sblymn *win->lines[*y]->lastchp); 247019bbd13Scgd #endif 24802559eb6Sjdc /* 24902559eb6Sjdc * Always update the change pointers. Otherwise, 25002559eb6Sjdc * we could end up not displaying 'blank' characters 25102559eb6Sjdc * when overlapping windows are displayed. 25202559eb6Sjdc */ 253*e124de36Sblymn newx = *x + win->ch_off; 254*e124de36Sblymn (*lp)->flags |= __ISDIRTY; 2558e3f5589Sjdc /* 2568e3f5589Sjdc * firstchp/lastchp are shared between 2578e3f5589Sjdc * parent window and sub-window. 2588e3f5589Sjdc */ 259*e124de36Sblymn if (newx < *(*lp)->firstchp) 260*e124de36Sblymn *(*lp)->firstchp = newx; 261*e124de36Sblymn if (newx > *(*lp)->lastchp) 262*e124de36Sblymn *(*lp)->lastchp = newx; 263019bbd13Scgd #ifdef DEBUG 2641f221324Sjdc __CTRACE(__CTRACE_INPUT, 2651f221324Sjdc "ADDBYTES: change gives f/l: %d/%d [%d/%d]\n", 266*e124de36Sblymn *(*lp)->firstchp, *(*lp)->lastchp, 267*e124de36Sblymn *(*lp)->firstchp - win->ch_off, 268*e124de36Sblymn *(*lp)->lastchp - win->ch_off); 269019bbd13Scgd #endif 270978ab4adSjdc if (win->bch != ' ' && c == ' ') 271*e124de36Sblymn (*lp)->line[*x].ch = win->bch; 272978ab4adSjdc else 273*e124de36Sblymn (*lp)->line[*x].ch = c; 274*e124de36Sblymn 275978ab4adSjdc if (attributes & __COLOR) 276*e124de36Sblymn (*lp)->line[*x].attr = 277978ab4adSjdc attributes | (win->battr & ~__COLOR); 278978ab4adSjdc else 279*e124de36Sblymn (*lp)->line[*x].attr = attributes | win->battr; 280*e124de36Sblymn 281*e124de36Sblymn if (*x == win->maxx - 1) 282*e124de36Sblymn (*lp)->flags |= __ISPASTEOL; 283019bbd13Scgd else 284*e124de36Sblymn (*x)++; 285019bbd13Scgd #ifdef DEBUG 2861f221324Sjdc __CTRACE(__CTRACE_INPUT, 2871f221324Sjdc "ADDBYTES: 2: y = %d, x = %d, firstch = %d, " 2881f221324Sjdc "lastch = %d\n", 289*e124de36Sblymn *y, *x, *win->lines[*y]->firstchp, 290*e124de36Sblymn *win->lines[*y]->lastchp); 29161f28255Scgd #endif 29261f28255Scgd break; 29361f28255Scgd case '\n': 294*e124de36Sblymn PSYNCH_OUT; 29561f28255Scgd wclrtoeol(win); 296*e124de36Sblymn PSYNCH_IN; 29761f28255Scgd goto newline; 29861f28255Scgd case '\r': 299*e124de36Sblymn *x = 0; 300*e124de36Sblymn break; 30161f28255Scgd case '\b': 302*e124de36Sblymn if (--(*x) < 0) 303*e124de36Sblymn *x = 0; 30461f28255Scgd break; 30561f28255Scgd } 3068d259104Sblymn 30762a3457dSmycroft return (OK); 30861f28255Scgd } 309*e124de36Sblymn 310*e124de36Sblymn /* 311*e124de36Sblymn * _cursesi_addwchar - 312*e124de36Sblymn * Internal function to add a wide character and update the row 313*e124de36Sblymn * and column positions. 314*e124de36Sblymn */ 315*e124de36Sblymn int 316*e124de36Sblymn _cursesi_addwchar(WINDOW *win, __LINE **lnp, int *y, int *x, 317*e124de36Sblymn const cchar_t *wch) 318*e124de36Sblymn { 319*e124de36Sblymn #ifndef HAVE_WCHAR 320*e124de36Sblymn return (ERR); 321*e124de36Sblymn #else 322*e124de36Sblymn int sx = 0, ex = 0, cw = 0, i = 0, newx = 0; 323*e124de36Sblymn __LDATA *lp = &win->lines[*y]->line[*x], *tp = NULL; 324*e124de36Sblymn nschar_t *np = NULL; 325*e124de36Sblymn cchar_t cc; 326*e124de36Sblymn attr_t attributes; 327*e124de36Sblymn 328*e124de36Sblymn /* special characters handling */ 329*e124de36Sblymn switch (wch->vals[0]) { 330*e124de36Sblymn case L'\b': 331*e124de36Sblymn if (--*x < 0) 332*e124de36Sblymn *x = 0; 333*e124de36Sblymn win->curx = *x; 334*e124de36Sblymn return OK; 335*e124de36Sblymn case L'\r': 336*e124de36Sblymn win->curx = 0; 337*e124de36Sblymn return OK; 338*e124de36Sblymn case L'\n': 339*e124de36Sblymn wclrtoeol(win); 340*e124de36Sblymn PSYNCH_IN; 341*e124de36Sblymn *x = 0; 342*e124de36Sblymn (*lnp)->flags &= ~__ISPASTEOL; 343*e124de36Sblymn if (*y == win->scr_b) { 344*e124de36Sblymn if (!(win->flags & __SCROLLOK)) 345*e124de36Sblymn return ERR; 346*e124de36Sblymn PSYNCH_OUT; 347*e124de36Sblymn scroll(win); 348*e124de36Sblymn PSYNCH_IN; 349*e124de36Sblymn } else { 350*e124de36Sblymn (*y)++; 351*e124de36Sblymn } 352*e124de36Sblymn PSYNCH_OUT; 353*e124de36Sblymn return OK; 354*e124de36Sblymn case L'\t': 355*e124de36Sblymn cc.vals[0] = L' '; 356*e124de36Sblymn cc.elements = 1; 357*e124de36Sblymn cc.attributes = win->wattr; 358*e124de36Sblymn for (i = 0; i < 8 - (*x % 8); i++) { 359*e124de36Sblymn if (wadd_wch(win, &cc) == ERR) 360*e124de36Sblymn return ERR; 361*e124de36Sblymn } 362*e124de36Sblymn return OK; 363*e124de36Sblymn } 364*e124de36Sblymn 365*e124de36Sblymn /* check for non-spacing character */ 366*e124de36Sblymn if (!wcwidth(wch->vals[0])) { 367*e124de36Sblymn #ifdef DEBUG 368*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 369*e124de36Sblymn "_cursesi_addwchar: char '%c' is non-spacing\n", 370*e124de36Sblymn wch->vals[0]); 371*e124de36Sblymn #endif /* DEBUG */ 372*e124de36Sblymn cw = WCOL(*lp); 373*e124de36Sblymn if (cw < 0) { 374*e124de36Sblymn lp += cw; 375*e124de36Sblymn *x += cw; 376*e124de36Sblymn } 377*e124de36Sblymn for (i = 0; i < wch->elements; i++) { 378*e124de36Sblymn if (!(np = (nschar_t *) malloc(sizeof(nschar_t)))) 379*e124de36Sblymn return ERR;; 380*e124de36Sblymn np->ch = wch->vals[i]; 381*e124de36Sblymn np->next = lp->nsp; 382*e124de36Sblymn lp->nsp = np; 383*e124de36Sblymn } 384*e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 385*e124de36Sblymn newx = *x + win->ch_off; 386*e124de36Sblymn if (newx < *(*lnp)->firstchp) 387*e124de36Sblymn *(*lnp)->firstchp = newx; 388*e124de36Sblymn if (newx > *(*lnp)->lastchp) 389*e124de36Sblymn *(*lnp)->lastchp = newx; 390*e124de36Sblymn __touchline(win, *y, *x, *x); 391*e124de36Sblymn return OK; 392*e124de36Sblymn } 393*e124de36Sblymn /* check for new line first */ 394*e124de36Sblymn if ((*lnp)->flags & __ISPASTEOL) { 395*e124de36Sblymn *x = 0; 396*e124de36Sblymn (*lnp)->flags &= ~__ISPASTEOL; 397*e124de36Sblymn if (*y == win->scr_b) { 398*e124de36Sblymn if (!(win->flags & __SCROLLOK)) 399*e124de36Sblymn return ERR; 400*e124de36Sblymn PSYNCH_OUT; 401*e124de36Sblymn scroll(win); 402*e124de36Sblymn PSYNCH_IN; 403*e124de36Sblymn } else { 404*e124de36Sblymn (*y)++; 405*e124de36Sblymn } 406*e124de36Sblymn (*lnp) = win->lines[*y]; 407*e124de36Sblymn lp = &win->lines[*y]->line[*x]; 408*e124de36Sblymn } 409*e124de36Sblymn /* clear out the current character */ 410*e124de36Sblymn cw = WCOL(*lp); 411*e124de36Sblymn if (cw >= 0) { 412*e124de36Sblymn sx = *x; 413*e124de36Sblymn } else { 414*e124de36Sblymn for (sx = *x - 1; sx >= max(*x + cw, 0); sx--) { 415*e124de36Sblymn #ifdef DEBUG 416*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 417*e124de36Sblymn "_cursesi_addwchar: clear current char (%d,%d)\n", 418*e124de36Sblymn *y, sx); 419*e124de36Sblymn #endif /* DEBUG */ 420*e124de36Sblymn tp = &win->lines[*y]->line[sx]; 421*e124de36Sblymn tp->ch = (wchar_t) btowc((int) win->bch); 422*e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 423*e124de36Sblymn return ERR; 424*e124de36Sblymn 425*e124de36Sblymn tp->attr = win->battr; 426*e124de36Sblymn SET_WCOL(*tp, 1); 427*e124de36Sblymn } 428*e124de36Sblymn sx = *x + cw; 429*e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 430*e124de36Sblymn newx = sx + win->ch_off; 431*e124de36Sblymn if (newx < *(*lnp)->firstchp) 432*e124de36Sblymn *(*lnp)->firstchp = newx; 433*e124de36Sblymn } 434*e124de36Sblymn 435*e124de36Sblymn /* check for enough space before the end of line */ 436*e124de36Sblymn cw = wcwidth(wch->vals[0]); 437*e124de36Sblymn if (cw > win->maxx - *x) { 438*e124de36Sblymn #ifdef DEBUG 439*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 440*e124de36Sblymn "_cursesi_addwchar: clear EOL (%d,%d)\n", 441*e124de36Sblymn *y, *x); 442*e124de36Sblymn #endif /* DEBUG */ 443*e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 444*e124de36Sblymn newx = *x + win->ch_off; 445*e124de36Sblymn if (newx < *(*lnp)->firstchp) 446*e124de36Sblymn *(*lnp)->firstchp = newx; 447*e124de36Sblymn for (tp = lp; *x < win->maxx; tp++, (*x)++) { 448*e124de36Sblymn tp->ch = (wchar_t) btowc((int) win->bch); 449*e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 450*e124de36Sblymn return ERR; 451*e124de36Sblymn tp->attr = win->battr; 452*e124de36Sblymn SET_WCOL(*tp, 1); 453*e124de36Sblymn } 454*e124de36Sblymn newx = win->maxx - 1 + win->ch_off; 455*e124de36Sblymn if (newx > *(*lnp)->lastchp) 456*e124de36Sblymn *(*lnp)->lastchp = newx; 457*e124de36Sblymn __touchline(win, *y, sx, (int) win->maxx - 1); 458*e124de36Sblymn sx = *x = 0; 459*e124de36Sblymn if (*y == win->scr_b) { 460*e124de36Sblymn if (!(win->flags & __SCROLLOK)) 461*e124de36Sblymn return ERR; 462*e124de36Sblymn PSYNCH_OUT; 463*e124de36Sblymn scroll(win); 464*e124de36Sblymn PSYNCH_IN; 465*e124de36Sblymn } else { 466*e124de36Sblymn (*y)++; 467*e124de36Sblymn } 468*e124de36Sblymn lp = &win->lines[*y]->line[0]; 469*e124de36Sblymn (*lnp) = win->lines[*y]; 470*e124de36Sblymn } 471*e124de36Sblymn win->cury = *y; 472*e124de36Sblymn 473*e124de36Sblymn /* add spacing character */ 474*e124de36Sblymn #ifdef DEBUG 475*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 476*e124de36Sblymn "_cursesi_addwchar: add character (%d,%d) 0x%x\n", 477*e124de36Sblymn *y, *x, wch->vals[0]); 478*e124de36Sblymn #endif /* DEBUG */ 479*e124de36Sblymn (*lnp)->flags |= __ISDIRTY; 480*e124de36Sblymn newx = *x + win->ch_off; 481*e124de36Sblymn if (newx < *(*lnp)->firstchp) 482*e124de36Sblymn *(*lnp)->firstchp = newx; 483*e124de36Sblymn if (lp->nsp) { 484*e124de36Sblymn __cursesi_free_nsp(lp->nsp); 485*e124de36Sblymn lp->nsp = NULL; 486*e124de36Sblymn } 487*e124de36Sblymn 488*e124de36Sblymn lp->ch = wch->vals[0]; 489*e124de36Sblymn 490*e124de36Sblymn attributes = (win->wattr | wch->attributes) 491*e124de36Sblymn & (WA_ATTRIBUTES & ~__COLOR); 492*e124de36Sblymn if (wch->attributes & __COLOR) 493*e124de36Sblymn attributes |= wch->attributes & __COLOR; 494*e124de36Sblymn else if (win->wattr & __COLOR) 495*e124de36Sblymn attributes |= win->wattr & __COLOR; 496*e124de36Sblymn if (attributes & __COLOR) 497*e124de36Sblymn lp->attr = attributes | (win->battr & ~__COLOR); 498*e124de36Sblymn else 499*e124de36Sblymn lp->attr = attributes | win->battr; 500*e124de36Sblymn 501*e124de36Sblymn SET_WCOL(*lp, cw); 502*e124de36Sblymn 503*e124de36Sblymn #ifdef DEBUG 504*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 505*e124de36Sblymn "_cursesi_addwchar: add spacing char 0x%x, attr 0x%x\n", 506*e124de36Sblymn lp->ch, lp->attr); 507*e124de36Sblymn #endif /* DEBUG */ 508*e124de36Sblymn 509*e124de36Sblymn if (wch->elements > 1) { 510*e124de36Sblymn for (i = 1; i < wch->elements; i++) { 511*e124de36Sblymn np = (nschar_t *)malloc(sizeof(nschar_t)); 512*e124de36Sblymn if (!np) 513*e124de36Sblymn return ERR;; 514*e124de36Sblymn np->ch = wch->vals[i]; 515*e124de36Sblymn np->next = lp->nsp; 516*e124de36Sblymn #ifdef DEBUG 517*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 518*e124de36Sblymn "_cursesi_addwchar: add non-spacing char 0x%x\n", np->ch); 519*e124de36Sblymn #endif /* DEBUG */ 520*e124de36Sblymn lp->nsp = np; 521*e124de36Sblymn } 522*e124de36Sblymn } 523*e124de36Sblymn #ifdef DEBUG 524*e124de36Sblymn __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: non-spacing list header: %p\n", 525*e124de36Sblymn lp->nsp); 526*e124de36Sblymn __CTRACE(__CTRACE_INPUT, "_cursesi_addwchar: add rest columns (%d:%d)\n", 527*e124de36Sblymn sx + 1, sx + cw - 1); 528*e124de36Sblymn #endif /* DEBUG */ 529*e124de36Sblymn for (tp = lp + 1, *x = sx + 1; *x - sx <= cw - 1; tp++, (*x)++) { 530*e124de36Sblymn if (tp->nsp) { 531*e124de36Sblymn __cursesi_free_nsp(tp->nsp); 532*e124de36Sblymn tp->nsp = NULL; 533*e124de36Sblymn } 534*e124de36Sblymn tp->ch = wch->vals[0]; 535*e124de36Sblymn tp->attr = lp->attr & WA_ATTRIBUTES; 536*e124de36Sblymn /* Mark as "continuation" cell */ 537*e124de36Sblymn tp->attr |= __WCWIDTH; 538*e124de36Sblymn } 539*e124de36Sblymn if (*x == win->maxx) { 540*e124de36Sblymn (*lnp)->flags |= __ISPASTEOL; 541*e124de36Sblymn newx = win->maxx - 1 + win->ch_off; 542*e124de36Sblymn if (newx > *(*lnp)->lastchp) 543*e124de36Sblymn *(*lnp)->lastchp = newx; 544*e124de36Sblymn __touchline(win, *y, sx, (int) win->maxx - 1); 545*e124de36Sblymn win->curx = sx; 546*e124de36Sblymn } else { 547*e124de36Sblymn win->curx = *x; 548*e124de36Sblymn 549*e124de36Sblymn /* clear the remining of the current characer */ 550*e124de36Sblymn if (*x && *x < win->maxx) { 551*e124de36Sblymn ex = sx + cw; 552*e124de36Sblymn tp = &win->lines[*y]->line[ex]; 553*e124de36Sblymn while (ex < win->maxx && WCOL(*tp) < 0) { 554*e124de36Sblymn #ifdef DEBUG 555*e124de36Sblymn __CTRACE(__CTRACE_INPUT, 556*e124de36Sblymn "_cursesi_addwchar: clear " 557*e124de36Sblymn "remaining of current char (%d,%d)nn", 558*e124de36Sblymn *y, ex); 559*e124de36Sblymn #endif /* DEBUG */ 560*e124de36Sblymn tp->ch = (wchar_t) btowc((int) win->bch); 561*e124de36Sblymn if (_cursesi_copy_nsp(win->bnsp, tp) == ERR) 562*e124de36Sblymn return ERR; 563*e124de36Sblymn tp->attr = win->battr; 564*e124de36Sblymn SET_WCOL(*tp, 1); 565*e124de36Sblymn tp++, ex++; 566*e124de36Sblymn } 567*e124de36Sblymn newx = ex - 1 + win->ch_off; 568*e124de36Sblymn if (newx > *(*lnp)->lastchp) 569*e124de36Sblymn *(*lnp)->lastchp = newx; 570*e124de36Sblymn __touchline(win, *y, sx, ex - 1); 571*e124de36Sblymn } 572*e124de36Sblymn } 573*e124de36Sblymn 574*e124de36Sblymn #ifdef DEBUG 575*e124de36Sblymn __CTRACE(__CTRACE_INPUT, "add_wch: %d : 0x%x\n", lp->ch, lp->attr); 576*e124de36Sblymn #endif /* DEBUG */ 577*e124de36Sblymn return OK; 578*e124de36Sblymn #endif 579*e124de36Sblymn } 580