1 /* $NetBSD: ins_wch.c,v 1.5 2010/02/23 19:48:26 drochner 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.5 2010/02/23 19:48:26 drochner 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; 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 if (wins_nwstr(win, ws, min(win->maxx - x, 8-(x % 8))) 150 == ERR) 151 return ERR; 152 return OK; 153 } 154 155 /* locate current cell */ 156 x = win->curx; 157 y = win->cury; 158 lnp = win->alines[ y ]; 159 start = &win->alines[ y ]->line[ x ]; 160 sx = x; 161 pcw = WCOL( *start ); 162 if (pcw < 0) { 163 start += pcw; 164 sx += pcw; 165 } 166 if ( cw > win->maxx - sx ) 167 return ERR; 168 lnp->flags |= __ISDIRTY; 169 newx = sx + win->ch_off; 170 if ( newx < *lnp->firstchp ) 171 *lnp->firstchp = newx; 172 173 /* shift all complete characters */ 174 #ifdef DEBUG 175 __CTRACE(__CTRACE_INPUT, "wins_wch: shift all characters\n"); 176 #endif /* DEBUG */ 177 temp1 = &win->alines[ y ]->line[ win->maxx - 1 ]; 178 temp2 = temp1 - cw; 179 pcw = WCOL(*(temp2 + 1)); 180 if (pcw < 0) { 181 #ifdef DEBUG 182 __CTRACE(__CTRACE_INPUT, "wins_wch: clear EOL\n"); 183 #endif /* DEBUG */ 184 temp2 += pcw; 185 while ( temp1 > temp2 + cw ) { 186 np = temp1->nsp; 187 if (np) { 188 while ( np ) { 189 tnp = np->next; 190 free( np ); 191 np = tnp; 192 } 193 temp1->nsp = NULL; 194 } 195 temp1->ch = ( wchar_t )btowc(( int ) win->bch ); 196 if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR) 197 return ERR; 198 temp1->attr = win->battr; 199 SET_WCOL( *temp1, 1 ); 200 temp1--; 201 } 202 } 203 while ( temp2 >= start ) { 204 ( void )memcpy( temp1, temp2, sizeof( __LDATA )); 205 temp1--, temp2--; 206 } 207 208 /* update character under cursor */ 209 start->nsp = NULL; 210 start->ch = wch->vals[ 0 ]; 211 start->attr = wch->attributes & WA_ATTRIBUTES; 212 SET_WCOL( *start, cw ); 213 if ( wch->elements > 1 ) { 214 for ( i = 1; i < wch->elements; i++ ) { 215 np = (nschar_t *)malloc(sizeof(nschar_t)); 216 if (!np) 217 return ERR; 218 np->ch = wch->vals[ i ]; 219 np->next = start->nsp; 220 start->nsp = np; 221 } 222 } 223 #ifdef DEBUG 224 __CTRACE(__CTRACE_INPUT, "wins_wch: insert (%x,%x,%p)\n", 225 start->ch, start->attr, start->nsp); 226 #endif /* DEBUG */ 227 temp1 = start + 1; 228 ex = x + 1; 229 while ( ex - x < cw ) { 230 temp1->ch = wch->vals[ 0 ]; 231 SET_WCOL( *temp1, x - ex ); 232 temp1->nsp = NULL; 233 ex++, temp1++; 234 } 235 #ifdef DEBUG 236 { 237 __CTRACE(__CTRACE_INPUT, "--after---\n"); 238 for ( x = 0; x < win->maxx; x++ ) 239 __CTRACE(__CTRACE_INPUT, 240 "wins_wch: (0,%d)=(%x,%x,%p)\n", x, 241 win->alines[0]->line[x].ch, 242 win->alines[0]->line[x].attr, 243 win->alines[0]->line[x].nsp); 244 } 245 #endif /* DEBUG */ 246 newx = win->maxx - 1 + win->ch_off; 247 if ( newx > *lnp->lastchp ) 248 *lnp->lastchp = newx; 249 __touchline(win, y, sx, (int) win->maxx - 1); 250 251 return OK; 252 #endif /* HAVE_WCHAR */ 253 } 254