Home | History | Annotate | Line # | Download | only in libcurses
      1 /*   $NetBSD: insstr.c,v 1.12 2024/12/23 02:58:03 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 (at) arl.wustl.edu,ruibiao (at) 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: insstr.c,v 1.12 2024/12/23 02:58:03 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 #ifndef _CURSES_USE_MACROS
     49 
     50 /*
     51  * insstr --
     52  *	insert a multi-byte character string into the current window
     53  */
     54 int
     55 insstr(const char *str)
     56 {
     57 
     58 	return winsstr(stdscr, str);
     59 }
     60 
     61 /*
     62  * insnstr --
     63  *	insert a multi-byte character string into the current window
     64  *	with at most n characters
     65  */
     66 int
     67 insnstr(const char *str, int n)
     68 {
     69 
     70 	return winsnstr(stdscr, str, n);
     71 }
     72 
     73 /*
     74  * mvinsstr --
     75  *	  Do an insert-string on the line at (y, x).
     76  */
     77 int
     78 mvinsstr(int y, int x, const char *str)
     79 {
     80 
     81 	return mvwinsstr(stdscr, y, x, str);
     82 }
     83 
     84 /*
     85  * mvinsnstr --
     86  *	  Do an insert-n-string on the line at (y, x).
     87  */
     88 int
     89 mvinsnstr(int y, int x, const char *str, int n)
     90 {
     91 
     92 	return mvwinsnstr(stdscr, y, x, str, n);
     93 }
     94 
     95 /*
     96  * mvwinsstr --
     97  *	  Do an insert-string on the line at (y, x) in the given window.
     98  */
     99 int
    100 mvwinsstr(WINDOW *win, int y, int x, const char *str)
    101 {
    102 
    103 	if (wmove(win, y, x) == ERR)
    104 		return ERR;
    105 
    106 	return winsstr(win, str);
    107 }
    108 
    109 /*
    110  * mvwinsnstr --
    111  *	  Do an insert-n-string on the line at (y, x) in the given window.
    112  */
    113 int
    114 mvwinsnstr(WINDOW *win, int y, int x, const char *str, int n)
    115 {
    116 
    117 	if (wmove(win, y, x) == ERR)
    118 		return ERR;
    119 
    120 	return winsnstr(win, str, n);
    121 }
    122 
    123 #endif
    124 
    125 /*
    126  * winsstr --
    127  *	Do an insert-string on the line, leaving (cury, curx) unchanged.
    128  *	No wrapping.
    129  */
    130 int
    131 winsstr(WINDOW *win, const char *str)
    132 {
    133 
    134 	return winsnstr(win, str, -1);
    135 }
    136 
    137 /*
    138  * winsnstr --
    139  *	Do an insert-n-string on the line, leaving (cury, curx) unchanged.
    140  *	Performs wrapping.
    141  */
    142 int
    143 winsnstr(WINDOW *win, const char *str, int n)
    144 {
    145 	__LDATA	*end, *temp1, *temp2;
    146 	const char *scp;
    147 	int len, x;
    148 	__LINE *lnp;
    149 #ifdef HAVE_WCHAR
    150 	nschar_t *np, *tnp;
    151 #endif /* HAVE_WCHAR */
    152 
    153 	if (__predict_false(win == NULL))
    154 		return ERR;
    155 
    156 	/* find string length */
    157 	if (n > 0)
    158 		for (scp = str, len = 0; n-- && *scp++; ++len);
    159 	else
    160 		for (scp = str, len = 0; *scp++; ++len);
    161 	__CTRACE(__CTRACE_INPUT, "winsnstr: len = %d\n", len);
    162 
    163 	/* move string */
    164 	end = &win->alines[win->cury]->line[win->curx];
    165 	if (len < win->maxx - win->curx) {
    166 		__CTRACE(__CTRACE_INPUT, "winsnstr: shift %d cells\n", len);
    167 		temp1 = &win->alines[win->cury]->line[win->maxx - 1];
    168 		temp2 = temp1 - len;
    169 		while (temp2 >= end) {
    170 #ifdef HAVE_WCHAR
    171 			np = temp1->nsp;
    172 			if (np){
    173 				while (np) {
    174 					tnp = np->next;
    175 					free(np);
    176 					np = tnp;
    177 				}
    178 				temp1->nsp = NULL;
    179 			}
    180 #endif /* HAVE_WCHAR */
    181 			(void)memcpy(temp1, temp2, sizeof(__LDATA));
    182 			temp1--, temp2--;
    183 		}
    184 	}
    185 
    186 	for (scp = str, temp1 = end, x = win->curx;
    187 	     *scp && x < len + win->curx && x < win->maxx;
    188 	     scp++, temp1++, x++)
    189 	{
    190 		temp1->ch = (wchar_t)*scp & __CHARTEXT;
    191 		temp1->attr = win->wattr;
    192 		temp1->cflags &= ~CA_BACKGROUND;
    193 		temp1->cflags &= ~CA_CONTINUATION;
    194 #ifdef HAVE_WCHAR
    195 		temp1->wcols = 1;
    196 #endif /* HAVE_WCHAR */
    197 	}
    198 #ifdef DEBUG
    199 	{
    200 		int i;
    201 
    202 		for (i = win->curx; i < win->curx + len; i++) {
    203 			__CTRACE(__CTRACE_INPUT,
    204 			    "winsnstr: (%d,%d)=('%c',%x)\n", win->cury, i,
    205 			    win->alines[win->cury]->line[i].ch,
    206 			    win->alines[win->cury]->line[i].attr);
    207 		}
    208 	}
    209 #endif /* DEBUG */
    210 	lnp = win->alines[win->cury];
    211 	lnp->flags |= __ISDIRTY;
    212 	if (win->ch_off < *lnp->firstchp)
    213 		*lnp->firstchp = win->ch_off;
    214 	if (win->ch_off + win->maxx - 1 > *lnp->lastchp)
    215 		*lnp->lastchp = win->ch_off + win->maxx - 1;
    216 	__touchline(win, (int)win->cury, (int)win->curx, (int)win->maxx - 1);
    217 	__sync(win);
    218 	return OK;
    219 }
    220