Home | History | Annotate | Line # | Download | only in libcurses
ins_wstr.c revision 1.18
      1  1.18     blymn /*   $NetBSD: ins_wstr.c,v 1.18 2021/11/15 06:27:06 blymn Exp $ */
      2   1.1     blymn 
      3   1.1     blymn /*
      4   1.1     blymn  * Copyright (c) 2005 The NetBSD Foundation Inc.
      5   1.1     blymn  * All rights reserved.
      6   1.1     blymn  *
      7   1.1     blymn  * This code is derived from code donated to the NetBSD Foundation
      8   1.1     blymn  * by Ruibiao Qiu <ruibiao (at) arl.wustl.edu,ruibiao (at) gmail.com>.
      9   1.1     blymn  *
     10   1.1     blymn  *
     11   1.1     blymn  * Redistribution and use in source and binary forms, with or without
     12   1.1     blymn  * modification, are permitted provided that the following conditions
     13   1.1     blymn  * are met:
     14   1.1     blymn  * 1. Redistributions of source code must retain the above copyright
     15   1.1     blymn  *	notice, this list of conditions and the following disclaimer.
     16   1.1     blymn  * 2. Redistributions in binary form must reproduce the above copyright
     17   1.1     blymn  *	notice, this list of conditions and the following disclaimer in the
     18   1.1     blymn  *	documentation and/or other materials provided with the distribution.
     19   1.1     blymn  * 3. Neither the name of the NetBSD Foundation nor the names of its
     20   1.1     blymn  *	contributors may be used to endorse or promote products derived
     21   1.1     blymn  *	from this software without specific prior written permission.
     22   1.1     blymn  *
     23   1.1     blymn  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     24   1.1     blymn  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     25   1.1     blymn  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     26   1.1     blymn  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27   1.1     blymn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28   1.1     blymn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29   1.1     blymn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30   1.1     blymn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31   1.1     blymn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32   1.1     blymn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33   1.1     blymn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34   1.1     blymn  * SUCH DAMAGE.
     35   1.1     blymn  */
     36   1.1     blymn 
     37   1.1     blymn #include <sys/cdefs.h>
     38   1.1     blymn #ifndef lint
     39  1.18     blymn __RCSID("$NetBSD: ins_wstr.c,v 1.18 2021/11/15 06:27:06 blymn Exp $");
     40   1.1     blymn #endif						  /* not lint */
     41   1.1     blymn 
     42   1.1     blymn #include <string.h>
     43   1.1     blymn #include <stdlib.h>
     44   1.1     blymn 
     45   1.1     blymn #include "curses.h"
     46   1.1     blymn #include "curses_private.h"
     47   1.1     blymn 
     48   1.1     blymn /*
     49   1.1     blymn  * ins_wstr --
     50   1.6       wiz  *	insert a multi-character wide-character string into the current window
     51   1.1     blymn  */
     52   1.1     blymn int
     53   1.1     blymn ins_wstr(const wchar_t *wstr)
     54   1.1     blymn {
     55   1.1     blymn 	return wins_wstr(stdscr, wstr);
     56   1.1     blymn }
     57   1.1     blymn 
     58   1.1     blymn /*
     59   1.1     blymn  * ins_nwstr --
     60   1.6       wiz  *	insert a multi-character wide-character string into the current window
     61   1.1     blymn  *	with at most n characters
     62   1.1     blymn  */
     63   1.1     blymn int
     64   1.1     blymn ins_nwstr(const wchar_t *wstr, int n)
     65   1.1     blymn {
     66   1.1     blymn 	return wins_nwstr(stdscr, wstr, n);
     67   1.1     blymn }
     68   1.1     blymn 
     69   1.1     blymn /*
     70   1.1     blymn  * mvins_wstr --
     71   1.1     blymn  *	  Do an insert-string on the line at (y, x).
     72   1.1     blymn  */
     73   1.1     blymn int
     74   1.1     blymn mvins_wstr(int y, int x, const wchar_t *wstr)
     75   1.1     blymn {
     76   1.1     blymn 	return mvwins_wstr(stdscr, y, x, wstr);
     77   1.1     blymn }
     78   1.1     blymn 
     79   1.1     blymn /*
     80   1.1     blymn  * mvins_nwstr --
     81   1.1     blymn  *	  Do an insert-n-string on the line at (y, x).
     82   1.1     blymn  */
     83   1.1     blymn int
     84   1.1     blymn mvins_nwstr(int y, int x, const wchar_t *wstr, int n)
     85   1.1     blymn {
     86   1.1     blymn 	return mvwins_nwstr(stdscr, y, x, wstr, n);
     87   1.1     blymn }
     88   1.1     blymn 
     89   1.1     blymn /*
     90   1.1     blymn  * mvwins_wstr --
     91   1.1     blymn  *	  Do an insert-string on the line at (y, x) in the given window.
     92   1.1     blymn  */
     93   1.1     blymn int
     94   1.1     blymn mvwins_wstr(WINDOW *win, int y, int x, const wchar_t *wstr)
     95   1.1     blymn {
     96  1.14     blymn 	if (wmove(win, y, x) == ERR)
     97   1.1     blymn 		return ERR;
     98   1.1     blymn 
     99  1.15       uwe 	return wins_wstr(win, wstr);
    100   1.1     blymn }
    101   1.1     blymn 
    102   1.1     blymn /*
    103   1.1     blymn  * mvwins_nwstr --
    104   1.1     blymn  *	  Do an insert-n-string on the line at (y, x) in the given window.
    105   1.1     blymn  */
    106   1.1     blymn int
    107   1.1     blymn mvwins_nwstr(WINDOW *win, int y, int x, const wchar_t *wstr, int n)
    108   1.1     blymn {
    109  1.14     blymn 	if (wmove(win, y, x) == ERR)
    110   1.1     blymn 		return ERR;
    111   1.1     blymn 
    112  1.15       uwe 	return wins_nwstr(win, wstr, n);
    113   1.1     blymn }
    114   1.1     blymn 
    115   1.1     blymn 
    116   1.1     blymn /*
    117   1.1     blymn  * wins_wstr --
    118   1.1     blymn  *	Do an insert-string on the line, leaving (cury, curx) unchanged.
    119   1.1     blymn  */
    120   1.1     blymn int
    121   1.1     blymn wins_wstr(WINDOW *win, const wchar_t *wstr)
    122   1.1     blymn {
    123   1.1     blymn 	return wins_nwstr(win, wstr, -1);
    124   1.1     blymn }
    125   1.1     blymn 
    126   1.1     blymn /*
    127   1.1     blymn  * wins_nwstr --
    128   1.1     blymn  *	Do an insert-n-string on the line, leaving (cury, curx) unchanged.
    129   1.1     blymn  */
    130   1.1     blymn int
    131   1.1     blymn wins_nwstr(WINDOW *win, const wchar_t *wstr, int n)
    132   1.1     blymn {
    133   1.1     blymn 	__LDATA	 *start, *temp1, *temp2;
    134   1.1     blymn 	__LINE	  *lnp;
    135   1.1     blymn 	const wchar_t *scp;
    136  1.18     blymn 	cchar_t cc;
    137  1.18     blymn 	wchar_t *lstr, *slstr;
    138  1.18     blymn 	int i, width, len, lx, sx, x, y, tx, ty, cw, pcw, newx, tn, w;
    139   1.1     blymn 	wchar_t ws[] = L"		";
    140   1.1     blymn 
    141   1.1     blymn 	/* check for leading non-spacing character */
    142   1.1     blymn 	if (!wstr)
    143   1.1     blymn 		return OK;
    144   1.1     blymn 	cw = wcwidth(*wstr);
    145   1.5  drochner 	if (cw < 0)
    146   1.5  drochner 		cw = 1;
    147   1.1     blymn 	if (!cw)
    148   1.1     blymn 		return ERR;
    149   1.1     blymn 
    150  1.18     blymn 	lstr = malloc(sizeof(wchar_t) * win->maxx);
    151  1.18     blymn 	if (lstr == NULL)
    152  1.18     blymn 		return ERR;
    153  1.18     blymn 
    154   1.1     blymn 	scp = wstr + 1;
    155   1.1     blymn 	width = cw;
    156   1.1     blymn 	len = 1;
    157   1.1     blymn 	n--;
    158  1.18     blymn 	y = win->cury;
    159  1.18     blymn 	x = win->curx;
    160  1.18     blymn 	tn = n;
    161  1.18     blymn 
    162  1.18     blymn 	/*
    163  1.18     blymn 	 * Firstly, make sure the string will fit...
    164  1.18     blymn 	 */
    165   1.1     blymn 	while (*scp) {
    166  1.18     blymn 		if (!tn)
    167   1.1     blymn 			break;
    168  1.18     blymn 		switch (*scp) {
    169  1.18     blymn 			case L'\b':
    170  1.18     blymn 				if (--x < 0)
    171  1.18     blymn 					x = 0;
    172  1.18     blymn 				cw = wcwidth(*(scp - 1));
    173  1.18     blymn 				if (cw < 0)
    174  1.18     blymn 					cw = 1;
    175  1.18     blymn 				width -= cw;
    176  1.18     blymn 				scp++;
    177  1.18     blymn 				continue;;
    178  1.18     blymn 
    179  1.18     blymn 			case L'\r':
    180  1.18     blymn 				width = 0;
    181  1.18     blymn 				x = 0;
    182  1.18     blymn 				scp++;
    183  1.18     blymn 				continue;
    184  1.18     blymn 
    185  1.18     blymn 			case L'\n':
    186  1.18     blymn 				if (y == win->scr_b) {
    187  1.18     blymn 					if (!(win->flags & __SCROLLOK)) {
    188  1.18     blymn 						free(lstr);
    189  1.18     blymn 						return ERR;
    190  1.18     blymn 					}
    191  1.18     blymn 				}
    192  1.18     blymn 				y++;
    193  1.18     blymn 				scp++;
    194  1.18     blymn 				continue;
    195  1.18     blymn 
    196  1.18     blymn 			case L'\t':
    197  1.18     blymn 				w = min(win->maxx - x, TABSIZE - (x % TABSIZE));
    198  1.18     blymn 				width += w * wcwidth(ws[0]);
    199  1.18     blymn 				x += w * wcwidth(ws[0]);
    200  1.18     blymn 				scp++;
    201  1.18     blymn 				continue;
    202  1.18     blymn 		}
    203   1.5  drochner 		w = wcwidth(*scp);
    204   1.5  drochner 		if (w < 0)
    205   1.5  drochner 			w = 1;
    206  1.18     blymn 		tn--, width += w;
    207   1.1     blymn 		scp++;
    208   1.1     blymn 	}
    209   1.2     blymn 	__CTRACE(__CTRACE_INPUT, "wins_nwstr: width=%d,len=%d\n", width, len);
    210   1.1     blymn 
    211  1.18     blymn 	if (width > win->maxx - win->curx + 1) {
    212  1.18     blymn 		free(lstr);
    213   1.1     blymn 		return ERR;
    214   1.1     blymn 	}
    215  1.18     blymn 
    216  1.18     blymn 	scp = wstr;
    217  1.18     blymn 	x = win->curx;
    218  1.18     blymn 	y = win->cury;
    219  1.18     blymn 	len = 0;
    220  1.18     blymn 	width = 0;
    221  1.18     blymn 	slstr = lstr;
    222  1.18     blymn 
    223  1.18     blymn 	while (*scp && n) {
    224  1.18     blymn 		lstr = slstr;
    225  1.18     blymn 		lx = x;
    226  1.18     blymn 		while (*scp) {
    227  1.18     blymn 			if (!n)
    228  1.18     blymn 				break;
    229  1.18     blymn 			switch (*scp) {
    230  1.18     blymn 				case L'\b':
    231  1.18     blymn 					if (--x < 0)
    232  1.18     blymn 						x = 0;
    233  1.18     blymn 					if (--len < 0)
    234  1.18     blymn 						len = 0;
    235  1.18     blymn 					cw = wcwidth(*(scp - 1));
    236  1.18     blymn 					if (cw < 0)
    237  1.18     blymn 						cw = 1;
    238  1.18     blymn 					width -= cw;
    239  1.18     blymn 					scp++;
    240  1.18     blymn 					if (lstr != slstr)
    241  1.18     blymn 						lstr--;
    242  1.18     blymn 					continue;;
    243  1.18     blymn 
    244  1.18     blymn 				case L'\r':
    245  1.18     blymn 					width = 0;
    246  1.18     blymn 					len = 0;
    247  1.18     blymn 					x = 0;
    248  1.18     blymn 					scp++;
    249  1.18     blymn 					lstr = slstr;
    250  1.18     blymn 					continue;
    251  1.18     blymn 
    252  1.18     blymn 				case L'\n':
    253  1.18     blymn 					goto loopdone;
    254  1.18     blymn 					break;
    255  1.18     blymn 
    256  1.18     blymn 				case L'\t':
    257  1.18     blymn 					w = min(win->maxx - x,
    258  1.18     blymn 					    TABSIZE - (x % TABSIZE));
    259  1.18     blymn 					width += w * wcwidth(ws[0]);
    260  1.18     blymn 					x += w * wcwidth(ws[0]);
    261  1.18     blymn 					len += w;
    262  1.18     blymn 					scp++;
    263  1.18     blymn 					for (i = 0; i < w; i++ ) {
    264  1.18     blymn 						*lstr = *ws;
    265  1.18     blymn 						lstr++;
    266  1.18     blymn 					}
    267  1.18     blymn 					continue;
    268  1.18     blymn 			}
    269  1.18     blymn 			w = wcwidth(*scp);
    270  1.18     blymn 			if (w < 0)
    271  1.18     blymn 				w = 1;
    272  1.18     blymn 			*lstr = *scp;
    273  1.18     blymn 			n--, len++, width += w;
    274  1.18     blymn 			scp++, lstr++;
    275  1.18     blymn 		}
    276  1.18     blymn 
    277  1.18     blymn loopdone:
    278  1.18     blymn 		start = &win->alines[y]->line[x];
    279  1.18     blymn 		sx = x;
    280  1.18     blymn 		lnp = win->alines[y];
    281  1.18     blymn 		pcw = WCOL(*start);
    282  1.18     blymn 		if (pcw < 0) {
    283  1.18     blymn 			sx += pcw;
    284  1.18     blymn 			start += pcw;
    285  1.18     blymn 		}
    286  1.18     blymn 		__CTRACE(__CTRACE_INPUT, "wins_nwstr: start@(%d)\n", sx);
    287  1.18     blymn 		pcw = WCOL(*start);
    288  1.18     blymn 		lnp->flags |= __ISDIRTY;
    289  1.18     blymn 		newx = sx + win->ch_off;
    290  1.18     blymn 		if (newx < *lnp->firstchp)
    291  1.18     blymn 			*lnp->firstchp = newx;
    292   1.1     blymn #ifdef DEBUG
    293  1.18     blymn 		{
    294  1.18     blymn 			__CTRACE(__CTRACE_INPUT, "========before=======\n");
    295  1.18     blymn 			for (i = 0; i < win->maxx; i++)
    296   1.2     blymn 			__CTRACE(__CTRACE_INPUT,
    297  1.18     blymn 				    "wins_nwstr: (%d,%d)=(%x,%x,%p)\n",
    298  1.18     blymn 				    y, i, win->alines[y]->line[i].ch,
    299  1.18     blymn 				    win->alines[y]->line[i].attr,
    300  1.18     blymn 				    win->alines[y]->line[i].nsp);
    301  1.18     blymn 		}
    302   1.1     blymn #endif /* DEBUG */
    303   1.1     blymn 
    304  1.18     blymn 		/* shift all complete characters */
    305  1.18     blymn 		if (sx + width + pcw <= win->maxx) {
    306  1.18     blymn 			__CTRACE(__CTRACE_INPUT, "wins_nwstr: shift all characters by %d\n", width);
    307  1.18     blymn 			temp1 = &win->alines[y]->line[win->maxx - 1];
    308  1.18     blymn 			temp2 = temp1 - width;
    309  1.18     blymn 			pcw = WCOL(*(temp2 + 1));
    310  1.18     blymn 			if (pcw < 0) {
    311   1.2     blymn 				__CTRACE(__CTRACE_INPUT,
    312  1.18     blymn 				    "wins_nwstr: clear from %d to EOL(%d)\n",
    313  1.18     blymn 				    win->maxx + pcw, win->maxx - 1);
    314  1.18     blymn 				temp2 += pcw;
    315  1.18     blymn 				while (temp1 > temp2 + width) {
    316  1.18     blymn 					temp1->ch = (wchar_t)btowc((int) win->bch);
    317  1.18     blymn 					if (_cursesi_copy_nsp(win->bnsp, temp1) == ERR) {
    318  1.18     blymn 						free(lstr);
    319  1.18     blymn 						return ERR;
    320  1.18     blymn 					}
    321  1.18     blymn 					temp1->attr = win->battr;
    322  1.18     blymn 					SET_WCOL(*temp1, 1);
    323  1.18     blymn 					__CTRACE(__CTRACE_INPUT,
    324  1.18     blymn 					    "wins_nwstr: empty cell(%p)\n", temp1);
    325  1.18     blymn 					temp1--;
    326  1.18     blymn 				}
    327  1.18     blymn 			}
    328  1.18     blymn 			while (temp2 >= start) {
    329  1.18     blymn 				(void)memcpy(temp1, temp2, sizeof(__LDATA));
    330  1.18     blymn 				temp1--, temp2--;
    331  1.18     blymn 			}
    332  1.18     blymn #ifdef DEBUG
    333  1.18     blymn 			{
    334  1.18     blymn 				__CTRACE(__CTRACE_INPUT, "=====after shift====\n");
    335  1.18     blymn 				for (i = 0; i < win->maxx; i++)
    336  1.18     blymn 					__CTRACE(__CTRACE_INPUT,
    337  1.18     blymn 					    "wins_nwstr: (%d,%d)=(%x,%x,%p)\n",
    338  1.18     blymn 					    y, i,
    339  1.18     blymn 					    win->alines[y]->line[i].ch,
    340  1.18     blymn 					    win->alines[y]->line[i].attr,
    341  1.18     blymn 					    win->alines[y]->line[i].nsp);
    342  1.18     blymn 				__CTRACE(__CTRACE_INPUT, "=====lstr====\n");
    343  1.18     blymn 				for (i = 0; i < len; i++)
    344  1.18     blymn 					__CTRACE(__CTRACE_INPUT,
    345  1.18     blymn 					    "wins_nwstr: lstr[%d]= %x,\n",
    346  1.18     blymn 					    i, (unsigned) slstr[i]);
    347   1.1     blymn 			}
    348  1.18     blymn #endif /* DEBUG */
    349   1.1     blymn 		}
    350  1.18     blymn 
    351  1.18     blymn 		/* update string columns */
    352  1.18     blymn 		x = lx;
    353  1.18     blymn 		for (lstr = slstr, temp1 = start; len; len--, lstr++) {
    354  1.18     blymn 			lnp = win->alines[y];
    355  1.18     blymn 			cc.vals[0] = *lstr;
    356  1.18     blymn 			cc.elements = 1;
    357  1.18     blymn 			cc.attributes = win->wattr;
    358  1.18     blymn 			_cursesi_addwchar(win, &lnp, &y, &x, &cc, 0);
    359   1.1     blymn 		}
    360  1.18     blymn 
    361   1.1     blymn #ifdef DEBUG
    362   1.1     blymn 		{
    363  1.18     blymn 			__CTRACE(__CTRACE_INPUT, "lx = %d, x = %x\n", lx, x);
    364  1.18     blymn 			__CTRACE(__CTRACE_INPUT, "========after=======\n");
    365  1.18     blymn 			for (i = 0; i < win->maxx; i++)
    366   1.2     blymn 				__CTRACE(__CTRACE_INPUT,
    367   1.2     blymn 				    "wins_nwstr: (%d,%d)=(%x,%x,%p)\n",
    368  1.18     blymn 				    y, i,
    369  1.18     blymn 				    win->alines[y]->line[i].ch,
    370  1.18     blymn 				    win->alines[y]->line[i].attr,
    371  1.18     blymn 				    win->alines[y]->line[i].nsp);
    372   1.1     blymn 		}
    373   1.1     blymn #endif /* DEBUG */
    374   1.1     blymn 
    375  1.18     blymn 		__touchline(win, (int) y, lx, (int) win->maxx - 1);
    376  1.18     blymn 
    377  1.18     blymn 		/*
    378  1.18     blymn 		 * Handle the newline here - we don't need to check
    379  1.18     blymn 		 * if we are allowed to scroll because this was checked
    380  1.18     blymn 		 * already.
    381  1.18     blymn 		 */
    382  1.18     blymn 		if (*scp == '\n') {
    383  1.18     blymn 			tx = win->curx;
    384  1.18     blymn 			ty = win->cury;
    385  1.18     blymn 			win->curx = x;
    386  1.18     blymn 			win->cury = y;
    387  1.18     blymn 			wclrtoeol(win);
    388  1.18     blymn 			win->curx = tx;
    389  1.18     blymn 			win->cury = ty;
    390  1.18     blymn 			if (y == win->scr_b)
    391  1.18     blymn 				scroll(win);
    392  1.18     blymn 			else
    393  1.18     blymn 				y++;
    394  1.18     blymn 			scp++;
    395  1.18     blymn 
    396   1.1     blymn 		}
    397  1.18     blymn 
    398  1.18     blymn 		newx = win->maxx - 1 + win->ch_off;
    399  1.18     blymn 		if (newx > *lnp->lastchp)
    400  1.18     blymn 			*lnp->lastchp = newx;
    401   1.1     blymn 	}
    402  1.18     blymn 	free(lstr);
    403   1.9       roy 	__sync(win);
    404   1.1     blymn 	return OK;
    405   1.1     blymn }
    406