1/*   $NetBSD: insstr.c,v 1.11 2022/10/19 06:09:27 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: insstr.c,v 1.11 2022/10/19 06:09:27 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 */
54int
55insstr(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 */
66int
67insnstr(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 */
77int
78mvinsstr(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 */
88int
89mvinsnstr(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 */
99int
100mvwinsstr(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 */
113int
114mvwinsnstr(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 */
130int
131winsstr(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 */
142int
143winsnstr(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	/* find string length */
154	if (n > 0)
155		for (scp = str, len = 0; n-- && *scp++; ++len);
156	else
157		for (scp = str, len = 0; *scp++; ++len);
158	__CTRACE(__CTRACE_INPUT, "winsnstr: len = %d\n", len);
159
160	/* move string */
161	end = &win->alines[win->cury]->line[win->curx];
162	if (len < win->maxx - win->curx) {
163		__CTRACE(__CTRACE_INPUT, "winsnstr: shift %d cells\n", len);
164		temp1 = &win->alines[win->cury]->line[win->maxx - 1];
165		temp2 = temp1 - len;
166		while (temp2 >= end) {
167#ifdef HAVE_WCHAR
168			np = temp1->nsp;
169			if (np){
170				while (np) {
171					tnp = np->next;
172					free(np);
173					np = tnp;
174				}
175				temp1->nsp = NULL;
176			}
177#endif /* HAVE_WCHAR */
178			(void)memcpy(temp1, temp2, sizeof(__LDATA));
179			temp1--, temp2--;
180		}
181	}
182
183	for (scp = str, temp1 = end, x = win->curx;
184	     *scp && x < len + win->curx && x < win->maxx;
185	     scp++, temp1++, x++)
186	{
187		temp1->ch = (wchar_t)*scp & __CHARTEXT;
188		temp1->attr = win->wattr;
189		temp1->cflags &= ~CA_BACKGROUND;
190		temp1->cflags &= ~CA_CONTINUATION;
191#ifdef HAVE_WCHAR
192		temp1->wcols = 1;
193#endif /* HAVE_WCHAR */
194	}
195#ifdef DEBUG
196	{
197		int i;
198
199		for (i = win->curx; i < win->curx + len; i++) {
200			__CTRACE(__CTRACE_INPUT,
201			    "winsnstr: (%d,%d)=('%c',%x)\n", win->cury, i,
202			    win->alines[win->cury]->line[i].ch,
203			    win->alines[win->cury]->line[i].attr);
204		}
205	}
206#endif /* DEBUG */
207	lnp = win->alines[win->cury];
208	lnp->flags |= __ISDIRTY;
209	if (win->ch_off < *lnp->firstchp)
210		*lnp->firstchp = win->ch_off;
211	if (win->ch_off + win->maxx - 1 > *lnp->lastchp)
212		*lnp->lastchp = win->ch_off + win->maxx - 1;
213	__touchline(win, (int)win->cury, (int)win->curx, (int)win->maxx - 1);
214	__sync(win);
215	return OK;
216}
217