1 /* $NetBSD: ins_wch.c,v 1.3 2007/05/29 11:10:56 blymn 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.3 2007/05/29 11:10:56 blymn 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) 114 return wadd_wch( win, wch ); 115 116 #ifdef DEBUG 117 __CTRACE(__CTRACE_INPUT, "--before--\n"); 118 for ( x = 0; x < win->maxx; x++ ) 119 __CTRACE(__CTRACE_INPUT, "wins_wch: (0,%d)=(%x,%x,%p)\n", x, 120 win->lines[0]->line[x].ch, 121 win->lines[0]->line[x].attr, 122 win->lines[0]->line[x].nsp); 123 #endif /* DEBUG */ 124 x = win->curx; 125 y = win->cury; 126 #ifdef DEBUG 127 __CTRACE(__CTRACE_INPUT, "wins_wch: (%d,%d)\n", y, x); 128 #endif /* DEBUG */ 129 switch ( wch->vals[ 0 ]) { 130 case L'\b': 131 if ( --x < 0 ) 132 x = 0; 133 win->curx = x; 134 return OK; 135 case L'\r': 136 win->curx = 0; 137 return OK; 138 case L'\n': 139 wclrtoeol( win ); 140 if (y == win->scr_b) { 141 if (!(win->flags & __SCROLLOK)) 142 return ERR; 143 scroll(win); 144 } 145 return OK; 146 case L'\t': 147 if (wins_nwstr(win, ws, min(win->maxx - x, 8-(x % 8))) 148 == ERR) 149 return ERR; 150 return OK; 151 } 152 153 /* locate current cell */ 154 x = win->curx; 155 y = win->cury; 156 lnp = win->lines[ y ]; 157 start = &win->lines[ y ]->line[ x ]; 158 sx = x; 159 pcw = WCOL( *start ); 160 if (pcw < 0) { 161 start += pcw; 162 sx += pcw; 163 } 164 if ( cw > win->maxx - sx ) 165 return ERR; 166 lnp->flags |= __ISDIRTY; 167 newx = sx + win->ch_off; 168 if ( newx < *lnp->firstchp ) 169 *lnp->firstchp = newx; 170 171 /* shift all complete characters */ 172 #ifdef DEBUG 173 __CTRACE(__CTRACE_INPUT, "wins_wch: shift all characters\n"); 174 #endif /* DEBUG */ 175 temp1 = &win->lines[ y ]->line[ win->maxx - 1 ]; 176 temp2 = temp1 - cw; 177 pcw = WCOL(*(temp2 + 1)); 178 if (pcw < 0) { 179 #ifdef DEBUG 180 __CTRACE(__CTRACE_INPUT, "wins_wch: clear EOL\n"); 181 #endif /* DEBUG */ 182 temp2 += pcw; 183 while ( temp1 > temp2 + cw ) { 184 np = temp1->nsp; 185 if (np) { 186 while ( np ) { 187 tnp = np->next; 188 free( np ); 189 np = tnp; 190 } 191 temp1->nsp = NULL; 192 } 193 temp1->ch = ( wchar_t )btowc(( int ) win->bch ); 194 if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR) 195 return ERR; 196 temp1->attr = win->battr; 197 SET_WCOL( *temp1, 1 ); 198 temp1--; 199 } 200 } 201 while ( temp2 >= start ) { 202 ( void )memcpy( temp1, temp2, sizeof( __LDATA )); 203 temp1--, temp2--; 204 } 205 206 /* update character under cursor */ 207 start->nsp = NULL; 208 start->ch = wch->vals[ 0 ]; 209 start->attr = wch->attributes & WA_ATTRIBUTES; 210 SET_WCOL( *start, cw ); 211 if ( wch->elements > 1 ) { 212 for ( i = 1; i < wch->elements; i++ ) { 213 np = (nschar_t *)malloc(sizeof(nschar_t)); 214 if (!np) 215 return ERR; 216 np->ch = wch->vals[ i ]; 217 np->next = start->nsp; 218 start->nsp = np; 219 } 220 } 221 #ifdef DEBUG 222 __CTRACE(__CTRACE_INPUT, "wins_wch: insert (%x,%x,%p)\n", 223 start->ch, start->attr, start->nsp); 224 #endif /* DEBUG */ 225 temp1 = start + 1; 226 ex = x + 1; 227 while ( ex - x < cw ) { 228 temp1->ch = wch->vals[ 0 ]; 229 SET_WCOL( *temp1, x - ex ); 230 temp1->nsp = NULL; 231 ex++, temp1++; 232 } 233 #ifdef DEBUG 234 { 235 __CTRACE(__CTRACE_INPUT, "--after---\n"); 236 for ( x = 0; x < win->maxx; x++ ) 237 __CTRACE(__CTRACE_INPUT, 238 "wins_wch: (0,%d)=(%x,%x,%p)\n", x, 239 win->lines[0]->line[x].ch, 240 win->lines[0]->line[x].attr, 241 win->lines[0]->line[x].nsp); 242 } 243 #endif /* DEBUG */ 244 newx = win->maxx - 1 + win->ch_off; 245 if ( newx > *lnp->lastchp ) 246 *lnp->lastchp = newx; 247 __touchline(win, y, sx, (int) win->maxx - 1); 248 249 return OK; 250 #endif /* HAVE_WCHAR */ 251 } 252