1 /* $NetBSD: ins_wch.c,v 1.6 2013/10/16 19:59:29 roy Exp $ */ 2 3 /* 4 * Copyright (c) 2005 The NetBSD Foundation Inc. 5 * All rights reserved. 6 * 7 * This code is derived from code donated to the NetBSD Foundation 8 * by Ruibiao Qiu <ruibiao@arl.wustl.edu,ruibiao@gmail.com>. 9 * 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the NetBSD Foundation nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 24 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include <sys/cdefs.h> 38 #ifndef lint 39 __RCSID("$NetBSD: ins_wch.c,v 1.6 2013/10/16 19:59:29 roy Exp $"); 40 #endif /* not lint */ 41 42 #include <string.h> 43 #include <stdlib.h> 44 45 #include "curses.h" 46 #include "curses_private.h" 47 48 /* 49 * ins_wch -- 50 * Do an insert-char on the line, leaving (cury, curx) unchanged. 51 */ 52 int 53 ins_wch(const cchar_t *wch) 54 { 55 #ifndef HAVE_WCHAR 56 return ERR; 57 #else 58 return wins_wch(stdscr, wch); 59 #endif /* HAVE_WCHAR */ 60 } 61 62 /* 63 * mvins_wch -- 64 * Do an insert-char on the line at (y, x). 65 */ 66 int 67 mvins_wch(int y, int x, const cchar_t *wch) 68 { 69 #ifndef HAVE_WCHAR 70 return ERR; 71 #else 72 return mvwins_wch(stdscr, y, x, wch); 73 #endif /* HAVE_WCHAR */ 74 } 75 76 /* 77 * mvwins_wch -- 78 * Do an insert-char on the line at (y, x) in the given window. 79 */ 80 int 81 mvwins_wch(WINDOW *win, int y, int x, const cchar_t *wch) 82 { 83 #ifndef HAVE_WCHAR 84 return ERR; 85 #else 86 if (wmove(win, y, x) == ERR) 87 return ERR; 88 89 return wins_wch(stdscr, wch); 90 #endif /* HAVE_WCHAR */ 91 } 92 93 /* 94 * wins_wch -- 95 * Do an insert-char on the line, leaving (cury, curx) unchanged. 96 */ 97 int 98 wins_wch(WINDOW *win, const cchar_t *wch) 99 { 100 #ifndef HAVE_WCHAR 101 return ERR; 102 #else 103 __LDATA *start, *temp1, *temp2; 104 __LINE *lnp; 105 int cw, pcw, x, y, sx, ex, newx, i, tabsize; 106 nschar_t *np, *tnp; 107 wchar_t ws[] = L" "; 108 109 /* check for non-spacing characters */ 110 if ( !wch ) 111 return OK; 112 cw = wcwidth(wch->vals[0]); 113 if (cw < 0) 114 cw = 1; 115 if (!cw) 116 return wadd_wch( win, wch ); 117 118 #ifdef DEBUG 119 __CTRACE(__CTRACE_INPUT, "--before--\n"); 120 for ( x = 0; x < win->maxx; x++ ) 121 __CTRACE(__CTRACE_INPUT, "wins_wch: (0,%d)=(%x,%x,%p)\n", x, 122 win->alines[0]->line[x].ch, 123 win->alines[0]->line[x].attr, 124 win->alines[0]->line[x].nsp); 125 #endif /* DEBUG */ 126 x = win->curx; 127 y = win->cury; 128 #ifdef DEBUG 129 __CTRACE(__CTRACE_INPUT, "wins_wch: (%d,%d)\n", y, x); 130 #endif /* DEBUG */ 131 switch ( wch->vals[ 0 ]) { 132 case L'\b': 133 if ( --x < 0 ) 134 x = 0; 135 win->curx = x; 136 return OK; 137 case L'\r': 138 win->curx = 0; 139 return OK; 140 case L'\n': 141 wclrtoeol( win ); 142 if (y == win->scr_b) { 143 if (!(win->flags & __SCROLLOK)) 144 return ERR; 145 scroll(win); 146 } 147 return OK; 148 case L'\t': 149 tabsize = win->screen->TABSIZE; 150 if (wins_nwstr(win, ws, min(win->maxx - x, 151 tabsize - (x % tabsize))) == ERR) 152 return ERR; 153 return OK; 154 } 155 156 /* locate current cell */ 157 x = win->curx; 158 y = win->cury; 159 lnp = win->alines[ y ]; 160 start = &win->alines[ y ]->line[ x ]; 161 sx = x; 162 pcw = WCOL( *start ); 163 if (pcw < 0) { 164 start += pcw; 165 sx += pcw; 166 } 167 if ( cw > win->maxx - sx ) 168 return ERR; 169 lnp->flags |= __ISDIRTY; 170 newx = sx + win->ch_off; 171 if ( newx < *lnp->firstchp ) 172 *lnp->firstchp = newx; 173 174 /* shift all complete characters */ 175 #ifdef DEBUG 176 __CTRACE(__CTRACE_INPUT, "wins_wch: shift all characters\n"); 177 #endif /* DEBUG */ 178 temp1 = &win->alines[ y ]->line[ win->maxx - 1 ]; 179 temp2 = temp1 - cw; 180 pcw = WCOL(*(temp2 + 1)); 181 if (pcw < 0) { 182 #ifdef DEBUG 183 __CTRACE(__CTRACE_INPUT, "wins_wch: clear EOL\n"); 184 #endif /* DEBUG */ 185 temp2 += pcw; 186 while ( temp1 > temp2 + cw ) { 187 np = temp1->nsp; 188 if (np) { 189 while ( np ) { 190 tnp = np->next; 191 free( np ); 192 np = tnp; 193 } 194 temp1->nsp = NULL; 195 } 196 temp1->ch = ( wchar_t )btowc(( int ) win->bch ); 197 if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR) 198 return ERR; 199 temp1->attr = win->battr; 200 SET_WCOL( *temp1, 1 ); 201 temp1--; 202 } 203 } 204 while ( temp2 >= start ) { 205 ( void )memcpy( temp1, temp2, sizeof( __LDATA )); 206 temp1--, temp2--; 207 } 208 209 /* update character under cursor */ 210 start->nsp = NULL; 211 start->ch = wch->vals[ 0 ]; 212 start->attr = wch->attributes & WA_ATTRIBUTES; 213 SET_WCOL( *start, cw ); 214 if ( wch->elements > 1 ) { 215 for ( i = 1; i < wch->elements; i++ ) { 216 np = (nschar_t *)malloc(sizeof(nschar_t)); 217 if (!np) 218 return ERR; 219 np->ch = wch->vals[ i ]; 220 np->next = start->nsp; 221 start->nsp = np; 222 } 223 } 224 #ifdef DEBUG 225 __CTRACE(__CTRACE_INPUT, "wins_wch: insert (%x,%x,%p)\n", 226 start->ch, start->attr, start->nsp); 227 #endif /* DEBUG */ 228 temp1 = start + 1; 229 ex = x + 1; 230 while ( ex - x < cw ) { 231 temp1->ch = wch->vals[ 0 ]; 232 SET_WCOL( *temp1, x - ex ); 233 temp1->nsp = NULL; 234 ex++, temp1++; 235 } 236 #ifdef DEBUG 237 { 238 __CTRACE(__CTRACE_INPUT, "--after---\n"); 239 for ( x = 0; x < win->maxx; x++ ) 240 __CTRACE(__CTRACE_INPUT, 241 "wins_wch: (0,%d)=(%x,%x,%p)\n", x, 242 win->alines[0]->line[x].ch, 243 win->alines[0]->line[x].attr, 244 win->alines[0]->line[x].nsp); 245 } 246 #endif /* DEBUG */ 247 newx = win->maxx - 1 + win->ch_off; 248 if ( newx > *lnp->lastchp ) 249 *lnp->lastchp = newx; 250 __touchline(win, y, sx, (int) win->maxx - 1); 251 252 return OK; 253 #endif /* HAVE_WCHAR */ 254 } 255