1*84d9c625SLionel Sambuc /* $NetBSD: ins_wch.c,v 1.6 2013/10/16 19:59:29 roy Exp $ */
251ffecc1SBen Gras
351ffecc1SBen Gras /*
451ffecc1SBen Gras * Copyright (c) 2005 The NetBSD Foundation Inc.
551ffecc1SBen Gras * All rights reserved.
651ffecc1SBen Gras *
751ffecc1SBen Gras * This code is derived from code donated to the NetBSD Foundation
851ffecc1SBen Gras * by Ruibiao Qiu <ruibiao@arl.wustl.edu,ruibiao@gmail.com>.
951ffecc1SBen Gras *
1051ffecc1SBen Gras *
1151ffecc1SBen Gras * Redistribution and use in source and binary forms, with or without
1251ffecc1SBen Gras * modification, are permitted provided that the following conditions
1351ffecc1SBen Gras * are met:
1451ffecc1SBen Gras * 1. Redistributions of source code must retain the above copyright
1551ffecc1SBen Gras * notice, this list of conditions and the following disclaimer.
1651ffecc1SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
1751ffecc1SBen Gras * notice, this list of conditions and the following disclaimer in the
1851ffecc1SBen Gras * documentation and/or other materials provided with the distribution.
1951ffecc1SBen Gras * 3. Neither the name of the NetBSD Foundation nor the names of its
2051ffecc1SBen Gras * contributors may be used to endorse or promote products derived
2151ffecc1SBen Gras * from this software without specific prior written permission.
2251ffecc1SBen Gras *
2351ffecc1SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
2451ffecc1SBen Gras * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
2551ffecc1SBen Gras * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2651ffecc1SBen Gras * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2751ffecc1SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2851ffecc1SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2951ffecc1SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3051ffecc1SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3151ffecc1SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3251ffecc1SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3351ffecc1SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3451ffecc1SBen Gras * SUCH DAMAGE.
3551ffecc1SBen Gras */
3651ffecc1SBen Gras
3751ffecc1SBen Gras #include <sys/cdefs.h>
3851ffecc1SBen Gras #ifndef lint
39*84d9c625SLionel Sambuc __RCSID("$NetBSD: ins_wch.c,v 1.6 2013/10/16 19:59:29 roy Exp $");
4051ffecc1SBen Gras #endif /* not lint */
4151ffecc1SBen Gras
4251ffecc1SBen Gras #include <string.h>
4351ffecc1SBen Gras #include <stdlib.h>
4451ffecc1SBen Gras
4551ffecc1SBen Gras #include "curses.h"
4651ffecc1SBen Gras #include "curses_private.h"
4751ffecc1SBen Gras
4851ffecc1SBen Gras /*
4951ffecc1SBen Gras * ins_wch --
5051ffecc1SBen Gras * Do an insert-char on the line, leaving (cury, curx) unchanged.
5151ffecc1SBen Gras */
5251ffecc1SBen Gras int
ins_wch(const cchar_t * wch)5351ffecc1SBen Gras ins_wch(const cchar_t *wch)
5451ffecc1SBen Gras {
5551ffecc1SBen Gras #ifndef HAVE_WCHAR
5651ffecc1SBen Gras return ERR;
5751ffecc1SBen Gras #else
5851ffecc1SBen Gras return wins_wch(stdscr, wch);
5951ffecc1SBen Gras #endif /* HAVE_WCHAR */
6051ffecc1SBen Gras }
6151ffecc1SBen Gras
6251ffecc1SBen Gras /*
6351ffecc1SBen Gras * mvins_wch --
6451ffecc1SBen Gras * Do an insert-char on the line at (y, x).
6551ffecc1SBen Gras */
6651ffecc1SBen Gras int
mvins_wch(int y,int x,const cchar_t * wch)6751ffecc1SBen Gras mvins_wch(int y, int x, const cchar_t *wch)
6851ffecc1SBen Gras {
6951ffecc1SBen Gras #ifndef HAVE_WCHAR
7051ffecc1SBen Gras return ERR;
7151ffecc1SBen Gras #else
7251ffecc1SBen Gras return mvwins_wch(stdscr, y, x, wch);
7351ffecc1SBen Gras #endif /* HAVE_WCHAR */
7451ffecc1SBen Gras }
7551ffecc1SBen Gras
7651ffecc1SBen Gras /*
7751ffecc1SBen Gras * mvwins_wch --
7851ffecc1SBen Gras * Do an insert-char on the line at (y, x) in the given window.
7951ffecc1SBen Gras */
8051ffecc1SBen Gras int
mvwins_wch(WINDOW * win,int y,int x,const cchar_t * wch)8151ffecc1SBen Gras mvwins_wch(WINDOW *win, int y, int x, const cchar_t *wch)
8251ffecc1SBen Gras {
8351ffecc1SBen Gras #ifndef HAVE_WCHAR
8451ffecc1SBen Gras return ERR;
8551ffecc1SBen Gras #else
8651ffecc1SBen Gras if (wmove(win, y, x) == ERR)
8751ffecc1SBen Gras return ERR;
8851ffecc1SBen Gras
8951ffecc1SBen Gras return wins_wch(stdscr, wch);
9051ffecc1SBen Gras #endif /* HAVE_WCHAR */
9151ffecc1SBen Gras }
9251ffecc1SBen Gras
9351ffecc1SBen Gras /*
9451ffecc1SBen Gras * wins_wch --
9551ffecc1SBen Gras * Do an insert-char on the line, leaving (cury, curx) unchanged.
9651ffecc1SBen Gras */
9751ffecc1SBen Gras int
wins_wch(WINDOW * win,const cchar_t * wch)9851ffecc1SBen Gras wins_wch(WINDOW *win, const cchar_t *wch)
9951ffecc1SBen Gras {
10051ffecc1SBen Gras #ifndef HAVE_WCHAR
10151ffecc1SBen Gras return ERR;
10251ffecc1SBen Gras #else
10351ffecc1SBen Gras __LDATA *start, *temp1, *temp2;
10451ffecc1SBen Gras __LINE *lnp;
105*84d9c625SLionel Sambuc int cw, pcw, x, y, sx, ex, newx, i, tabsize;
10651ffecc1SBen Gras nschar_t *np, *tnp;
10751ffecc1SBen Gras wchar_t ws[] = L" ";
10851ffecc1SBen Gras
10951ffecc1SBen Gras /* check for non-spacing characters */
11051ffecc1SBen Gras if ( !wch )
11151ffecc1SBen Gras return OK;
11251ffecc1SBen Gras cw = wcwidth(wch->vals[0]);
11351ffecc1SBen Gras if (cw < 0)
11451ffecc1SBen Gras cw = 1;
11551ffecc1SBen Gras if (!cw)
11651ffecc1SBen Gras return wadd_wch( win, wch );
11751ffecc1SBen Gras
11851ffecc1SBen Gras #ifdef DEBUG
11951ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "--before--\n");
12051ffecc1SBen Gras for ( x = 0; x < win->maxx; x++ )
12151ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wins_wch: (0,%d)=(%x,%x,%p)\n", x,
12251ffecc1SBen Gras win->alines[0]->line[x].ch,
12351ffecc1SBen Gras win->alines[0]->line[x].attr,
12451ffecc1SBen Gras win->alines[0]->line[x].nsp);
12551ffecc1SBen Gras #endif /* DEBUG */
12651ffecc1SBen Gras x = win->curx;
12751ffecc1SBen Gras y = win->cury;
12851ffecc1SBen Gras #ifdef DEBUG
12951ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wins_wch: (%d,%d)\n", y, x);
13051ffecc1SBen Gras #endif /* DEBUG */
13151ffecc1SBen Gras switch ( wch->vals[ 0 ]) {
13251ffecc1SBen Gras case L'\b':
13351ffecc1SBen Gras if ( --x < 0 )
13451ffecc1SBen Gras x = 0;
13551ffecc1SBen Gras win->curx = x;
13651ffecc1SBen Gras return OK;
13751ffecc1SBen Gras case L'\r':
13851ffecc1SBen Gras win->curx = 0;
13951ffecc1SBen Gras return OK;
14051ffecc1SBen Gras case L'\n':
14151ffecc1SBen Gras wclrtoeol( win );
14251ffecc1SBen Gras if (y == win->scr_b) {
14351ffecc1SBen Gras if (!(win->flags & __SCROLLOK))
14451ffecc1SBen Gras return ERR;
14551ffecc1SBen Gras scroll(win);
14651ffecc1SBen Gras }
14751ffecc1SBen Gras return OK;
14851ffecc1SBen Gras case L'\t':
149*84d9c625SLionel Sambuc tabsize = win->screen->TABSIZE;
150*84d9c625SLionel Sambuc if (wins_nwstr(win, ws, min(win->maxx - x,
151*84d9c625SLionel Sambuc tabsize - (x % tabsize))) == ERR)
15251ffecc1SBen Gras return ERR;
15351ffecc1SBen Gras return OK;
15451ffecc1SBen Gras }
15551ffecc1SBen Gras
15651ffecc1SBen Gras /* locate current cell */
15751ffecc1SBen Gras x = win->curx;
15851ffecc1SBen Gras y = win->cury;
15951ffecc1SBen Gras lnp = win->alines[ y ];
16051ffecc1SBen Gras start = &win->alines[ y ]->line[ x ];
16151ffecc1SBen Gras sx = x;
16251ffecc1SBen Gras pcw = WCOL( *start );
16351ffecc1SBen Gras if (pcw < 0) {
16451ffecc1SBen Gras start += pcw;
16551ffecc1SBen Gras sx += pcw;
16651ffecc1SBen Gras }
16751ffecc1SBen Gras if ( cw > win->maxx - sx )
16851ffecc1SBen Gras return ERR;
16951ffecc1SBen Gras lnp->flags |= __ISDIRTY;
17051ffecc1SBen Gras newx = sx + win->ch_off;
17151ffecc1SBen Gras if ( newx < *lnp->firstchp )
17251ffecc1SBen Gras *lnp->firstchp = newx;
17351ffecc1SBen Gras
17451ffecc1SBen Gras /* shift all complete characters */
17551ffecc1SBen Gras #ifdef DEBUG
17651ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wins_wch: shift all characters\n");
17751ffecc1SBen Gras #endif /* DEBUG */
17851ffecc1SBen Gras temp1 = &win->alines[ y ]->line[ win->maxx - 1 ];
17951ffecc1SBen Gras temp2 = temp1 - cw;
18051ffecc1SBen Gras pcw = WCOL(*(temp2 + 1));
18151ffecc1SBen Gras if (pcw < 0) {
18251ffecc1SBen Gras #ifdef DEBUG
18351ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wins_wch: clear EOL\n");
18451ffecc1SBen Gras #endif /* DEBUG */
18551ffecc1SBen Gras temp2 += pcw;
18651ffecc1SBen Gras while ( temp1 > temp2 + cw ) {
18751ffecc1SBen Gras np = temp1->nsp;
18851ffecc1SBen Gras if (np) {
18951ffecc1SBen Gras while ( np ) {
19051ffecc1SBen Gras tnp = np->next;
19151ffecc1SBen Gras free( np );
19251ffecc1SBen Gras np = tnp;
19351ffecc1SBen Gras }
19451ffecc1SBen Gras temp1->nsp = NULL;
19551ffecc1SBen Gras }
19651ffecc1SBen Gras temp1->ch = ( wchar_t )btowc(( int ) win->bch );
19751ffecc1SBen Gras if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR)
19851ffecc1SBen Gras return ERR;
19951ffecc1SBen Gras temp1->attr = win->battr;
20051ffecc1SBen Gras SET_WCOL( *temp1, 1 );
20151ffecc1SBen Gras temp1--;
20251ffecc1SBen Gras }
20351ffecc1SBen Gras }
20451ffecc1SBen Gras while ( temp2 >= start ) {
20551ffecc1SBen Gras ( void )memcpy( temp1, temp2, sizeof( __LDATA ));
20651ffecc1SBen Gras temp1--, temp2--;
20751ffecc1SBen Gras }
20851ffecc1SBen Gras
20951ffecc1SBen Gras /* update character under cursor */
21051ffecc1SBen Gras start->nsp = NULL;
21151ffecc1SBen Gras start->ch = wch->vals[ 0 ];
21251ffecc1SBen Gras start->attr = wch->attributes & WA_ATTRIBUTES;
21351ffecc1SBen Gras SET_WCOL( *start, cw );
21451ffecc1SBen Gras if ( wch->elements > 1 ) {
21551ffecc1SBen Gras for ( i = 1; i < wch->elements; i++ ) {
21651ffecc1SBen Gras np = (nschar_t *)malloc(sizeof(nschar_t));
21751ffecc1SBen Gras if (!np)
21851ffecc1SBen Gras return ERR;
21951ffecc1SBen Gras np->ch = wch->vals[ i ];
22051ffecc1SBen Gras np->next = start->nsp;
22151ffecc1SBen Gras start->nsp = np;
22251ffecc1SBen Gras }
22351ffecc1SBen Gras }
22451ffecc1SBen Gras #ifdef DEBUG
22551ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "wins_wch: insert (%x,%x,%p)\n",
22651ffecc1SBen Gras start->ch, start->attr, start->nsp);
22751ffecc1SBen Gras #endif /* DEBUG */
22851ffecc1SBen Gras temp1 = start + 1;
22951ffecc1SBen Gras ex = x + 1;
23051ffecc1SBen Gras while ( ex - x < cw ) {
23151ffecc1SBen Gras temp1->ch = wch->vals[ 0 ];
23251ffecc1SBen Gras SET_WCOL( *temp1, x - ex );
23351ffecc1SBen Gras temp1->nsp = NULL;
23451ffecc1SBen Gras ex++, temp1++;
23551ffecc1SBen Gras }
23651ffecc1SBen Gras #ifdef DEBUG
23751ffecc1SBen Gras {
23851ffecc1SBen Gras __CTRACE(__CTRACE_INPUT, "--after---\n");
23951ffecc1SBen Gras for ( x = 0; x < win->maxx; x++ )
24051ffecc1SBen Gras __CTRACE(__CTRACE_INPUT,
24151ffecc1SBen Gras "wins_wch: (0,%d)=(%x,%x,%p)\n", x,
24251ffecc1SBen Gras win->alines[0]->line[x].ch,
24351ffecc1SBen Gras win->alines[0]->line[x].attr,
24451ffecc1SBen Gras win->alines[0]->line[x].nsp);
24551ffecc1SBen Gras }
24651ffecc1SBen Gras #endif /* DEBUG */
24751ffecc1SBen Gras newx = win->maxx - 1 + win->ch_off;
24851ffecc1SBen Gras if ( newx > *lnp->lastchp )
24951ffecc1SBen Gras *lnp->lastchp = newx;
25051ffecc1SBen Gras __touchline(win, y, sx, (int) win->maxx - 1);
25151ffecc1SBen Gras
25251ffecc1SBen Gras return OK;
25351ffecc1SBen Gras #endif /* HAVE_WCHAR */
25451ffecc1SBen Gras }
255