xref: /netbsd-src/lib/libcurses/insdelln.c (revision 6348e3f32a4431b45d07e1da16fd7b12725a45e7)
1 /*	$NetBSD: insdelln.c,v 1.24 2024/12/23 02:58:03 blymn Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Julian Coleman.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: insdelln.c,v 1.24 2024/12/23 02:58:03 blymn Exp $");
35 #endif				/* not lint */
36 
37 /*
38  * Based on deleteln.c and insertln.c -
39  * Copyright (c) 1981, 1993, 1994
40  *	The Regents of the University of California.  All rights reserved.
41  */
42 
43 #include <string.h>
44 #include <stdlib.h>
45 
46 #include "curses.h"
47 #include "curses_private.h"
48 
49 #ifndef _CURSES_USE_MACROS
50 
51 /*
52  * insdelln --
53  *	Insert or delete lines on stdscr, leaving (cury, curx) unchanged.
54  */
55 int
56 insdelln(int nlines)
57 {
58 
59 	return winsdelln(stdscr, nlines);
60 }
61 
62 #endif
63 
64 /*
65  * winsdelln --
66  *	Insert or delete lines on the window, leaving (cury, curx) unchanged.
67  */
68 int
69 winsdelln(WINDOW *win, int nlines)
70 {
71 	int     y, i, last;
72 	__LINE *temp;
73 #ifdef HAVE_WCHAR
74 	__LDATA *lp;
75 #endif /* HAVE_WCHAR */
76 	attr_t	attr;
77 
78 	__CTRACE(__CTRACE_LINE,
79 	    "winsdelln: (%p) cury=%d lines=%d\n", win, win->cury, nlines);
80 
81 	if (__predict_false(win == NULL))
82 		return ERR;
83 
84 	if (!nlines)
85 		return OK;
86 
87 	if (__using_color && win != curscr)
88 		attr = win->battr & __COLOR;
89 	else
90 		attr = 0;
91 
92 	if (nlines > 0) {
93 		/* Insert lines */
94 		if (win->cury < win->scr_t || win->cury > win->scr_b) {
95 			/*  Outside scrolling region */
96 			if (nlines > win->maxy - win->cury)
97 				nlines = win->maxy - win->cury;
98 			last = win->maxy - 1;
99 		} else {
100 			/* Inside scrolling region */
101 			if (nlines > win->scr_b + 1 - win->cury)
102 				nlines = win->scr_b + 1 - win->cury;
103 			last = win->scr_b;
104 		}
105 		for (y = last - nlines; y >= win->cury; --y) {
106 			win->alines[y]->flags &= ~__ISPASTEOL;
107 			win->alines[y + nlines]->flags &= ~__ISPASTEOL;
108 			if (win->orig == NULL) {
109 				temp = win->alines[y + nlines];
110 				win->alines[y + nlines] = win->alines[y];
111 				win->alines[y] = temp;
112 			} else {
113 				(void)memcpy(win->alines[y + nlines]->line,
114 				    win->alines[y]->line,
115 				    (size_t)win->maxx * __LDATASIZE);
116 			}
117 		}
118 		for (y = win->cury - 1 + nlines; y >= win->cury; --y)
119 			for (i = 0; i < win->maxx; i++) {
120 				win->alines[y]->line[i].ch = win->bch;
121 				win->alines[y]->line[i].attr = attr;
122 				win->alines[y]->line[i].cflags |=
123 				    CA_BACKGROUND;
124 				win->alines[y]->line[i].cflags &=
125 				    ~CA_CONTINUATION;
126 #ifdef HAVE_WCHAR
127 				lp = &win->alines[y]->line[i];
128 				if (_cursesi_copy_nsp(win->bnsp, lp) == ERR)
129 					return ERR;
130 				lp->wcols = 1;
131 #endif /* HAVE_WCHAR */
132 			}
133 		for (y = last; y >= win->cury; --y)
134 			__touchline(win, y, 0, (int)win->maxx - 1);
135 	} else {
136 		/* Delete nlines */
137 		nlines = 0 - nlines;
138 		if (win->cury < win->scr_t || win->cury > win->scr_b) {
139 			/*  Outside scrolling region */
140 			if (nlines > win->maxy - win->cury)
141 				nlines = win->maxy - win->cury;
142 			last = win->maxy;
143 		} else {
144 			/* Inside scrolling region */
145 			if (nlines > win->scr_b + 1 - win->cury)
146 				nlines = win->scr_b + 1 - win->cury;
147 			last = win->scr_b + 1;
148 		}
149 		for (y = win->cury; y < last - nlines; y++) {
150 			win->alines[y]->flags &= ~__ISPASTEOL;
151 			win->alines[y + nlines]->flags &= ~__ISPASTEOL;
152 			if (win->orig == NULL) {
153 				temp = win->alines[y];
154 				win->alines[y] = win->alines[y + nlines];
155 				win->alines[y + nlines] = temp;
156 			} else {
157 				(void)memcpy(win->alines[y]->line,
158 				    win->alines[y + nlines]->line,
159 				    (size_t)win->maxx * __LDATASIZE);
160 			}
161 		}
162 		for (y = last - nlines; y < last; y++)
163 			for (i = 0; i < win->maxx; i++) {
164 				win->alines[y]->line[i].ch = win->bch;
165 				win->alines[y]->line[i].attr = attr;
166 				win->alines[y]->line[i].cflags |=
167 				    CA_BACKGROUND;
168 				win->alines[y]->line[i].cflags &=
169 				    ~CA_CONTINUATION;
170 #ifdef HAVE_WCHAR
171 				lp = &win->alines[y]->line[i];
172 				lp->wcols = 1;
173 				if (_cursesi_copy_nsp(win->bnsp, lp) == ERR)
174 					return ERR;
175 #endif /* HAVE_WCHAR */
176 			}
177 		for (y = win->cury; y < last; y++)
178 			__touchline(win, y, 0, (int)win->maxx - 1);
179 	}
180 	if (win->orig != NULL)
181 		__id_subwins(win->orig);
182 	__sync(win);
183 	return OK;
184 }
185