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