1 1.35 blymn /* $NetBSD: touchwin.c,v 1.35 2024/12/23 02:58:04 blymn Exp $ */ 2 1.7 mikel 3 1.1 cgd /* 4 1.6 cgd * Copyright (c) 1981, 1993, 1994 5 1.4 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.19 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.7 mikel #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.7 mikel #if 0 35 1.6 cgd static char sccsid[] = "@(#)touchwin.c 8.2 (Berkeley) 5/4/94"; 36 1.7 mikel #else 37 1.35 blymn __RCSID("$NetBSD: touchwin.c,v 1.35 2024/12/23 02:58:04 blymn Exp $"); 38 1.7 mikel #endif 39 1.9 mrg #endif /* not lint */ 40 1.1 cgd 41 1.6 cgd #include "curses.h" 42 1.10 blymn #include "curses_private.h" 43 1.4 cgd 44 1.27 blymn static int _cursesi_touchline_force(WINDOW *, int, int, int, int); 45 1.27 blymn 46 1.4 cgd /* 47 1.29 roy * __sync -- 48 1.29 roy * To be called after each window change. 49 1.29 roy */ 50 1.29 roy void 51 1.29 roy __sync(WINDOW *win) 52 1.29 roy { 53 1.35 blymn if (__predict_false(win == NULL)) 54 1.35 blymn return; 55 1.29 roy 56 1.29 roy if (win->flags & __IMMEDOK) 57 1.29 roy wrefresh(win); 58 1.29 roy if (win->flags & __SYNCOK) 59 1.29 roy wsyncup(win); 60 1.29 roy } 61 1.29 roy 62 1.29 roy /* 63 1.13 blymn * is_linetouched -- 64 1.24 blymn * Indicate if line has been touched or not. 65 1.13 blymn */ 66 1.13 blymn bool 67 1.13 blymn is_linetouched(WINDOW *win, int line) 68 1.13 blymn { 69 1.35 blymn if (__predict_false(win == NULL)) 70 1.35 blymn return ERR; 71 1.35 blymn 72 1.13 blymn if (line > win->maxy) 73 1.13 blymn return FALSE; 74 1.16 blymn 75 1.31 blymn __CTRACE(__CTRACE_LINE, "is_linetouched: (%p, line %d, dirty %d)\n", 76 1.31 blymn win, line, (win->alines[line]->flags & __ISDIRTY)); 77 1.30 roy return (win->alines[line]->flags & __ISDIRTY) != 0; 78 1.13 blymn } 79 1.16 blymn 80 1.13 blymn /* 81 1.20 jdc * touchline -- 82 1.20 jdc * Touch count lines starting at start. This is the SUS v2 compliant 83 1.20 jdc * version. 84 1.4 cgd */ 85 1.4 cgd int 86 1.11 blymn touchline(WINDOW *win, int start, int count) 87 1.4 cgd { 88 1.23 jdc __CTRACE(__CTRACE_LINE, "touchline: (%p, %d, %d)\n", win, start, count); 89 1.13 blymn return wtouchln(win, start, count, 1); 90 1.13 blymn } 91 1.13 blymn 92 1.13 blymn /* 93 1.20 jdc * wredrawln -- 94 1.20 jdc * Mark count lines starting at start as corrupted. Implemented using 95 1.20 jdc * wtouchln(). 96 1.20 jdc */ 97 1.20 jdc int wredrawln(WINDOW *win, int start, int count) 98 1.20 jdc { 99 1.23 jdc __CTRACE(__CTRACE_LINE, "wredrawln: (%p, %d, %d)\n", win, start, count); 100 1.20 jdc return wtouchln(win, start, count, 1); 101 1.20 jdc } 102 1.20 jdc 103 1.20 jdc /* 104 1.13 blymn * is_wintouched -- 105 1.24 blymn * Check if the window has been touched. 106 1.13 blymn */ 107 1.13 blymn bool 108 1.13 blymn is_wintouched(WINDOW *win) 109 1.13 blymn { 110 1.13 blymn int y, maxy; 111 1.10 blymn 112 1.31 blymn __CTRACE(__CTRACE_LINE, "is_wintouched: (%p, maxy %d)\n", win, 113 1.31 blymn win->maxy); 114 1.35 blymn if (__predict_false(win == NULL)) 115 1.35 blymn return FALSE; 116 1.35 blymn 117 1.13 blymn maxy = win->maxy; 118 1.13 blymn for (y = 0; y < maxy; y++) { 119 1.13 blymn if (is_linetouched(win, y) == TRUE) 120 1.13 blymn return TRUE; 121 1.10 blymn } 122 1.10 blymn 123 1.13 blymn return FALSE; 124 1.4 cgd } 125 1.4 cgd 126 1.1 cgd /* 127 1.3 mycroft * touchwin -- 128 1.3 mycroft * Make it look like the whole window has been changed. 129 1.1 cgd */ 130 1.3 mycroft int 131 1.11 blymn touchwin(WINDOW *win) 132 1.1 cgd { 133 1.23 jdc __CTRACE(__CTRACE_LINE, "touchwin: (%p)\n", win); 134 1.20 jdc return wtouchln(win, 0, win->maxy, 1); 135 1.20 jdc } 136 1.20 jdc 137 1.20 jdc /* 138 1.20 jdc * redrawwin -- 139 1.20 jdc * Mark entire window as corrupted. Implemented using wtouchln(). 140 1.20 jdc */ 141 1.20 jdc int 142 1.20 jdc redrawwin(WINDOW *win) 143 1.20 jdc { 144 1.23 jdc __CTRACE(__CTRACE_LINE, "redrawwin: (%p)\n", win); 145 1.13 blymn return wtouchln(win, 0, win->maxy, 1); 146 1.13 blymn } 147 1.13 blymn 148 1.13 blymn /* 149 1.13 blymn * untouchwin -- 150 1.24 blymn * Make it look like the window has not been changed. 151 1.13 blymn */ 152 1.13 blymn int 153 1.13 blymn untouchwin(WINDOW *win) 154 1.13 blymn { 155 1.23 jdc __CTRACE(__CTRACE_LINE, "untouchwin: (%p)\n", win); 156 1.13 blymn return wtouchln(win, 0, win->maxy, 0); 157 1.4 cgd } 158 1.4 cgd 159 1.13 blymn /* 160 1.13 blymn * wtouchln -- 161 1.24 blymn * If changed is 1 then touch n lines starting at line. If changed 162 1.24 blymn * is 0 then mark the lines as unchanged. 163 1.13 blymn */ 164 1.13 blymn int 165 1.13 blymn wtouchln(WINDOW *win, int line, int n, int changed) 166 1.13 blymn { 167 1.14 mycroft int y; 168 1.14 mycroft __LINE *wlp; 169 1.13 blymn 170 1.23 jdc __CTRACE(__CTRACE_LINE, "wtouchln: (%p) %d, %d, %d\n", 171 1.23 jdc win, line, n, changed); 172 1.35 blymn if (__predict_false(win == NULL)) 173 1.35 blymn return FALSE; 174 1.35 blymn 175 1.32 uwe if (line < 0 || win->maxy <= line) 176 1.32 uwe return ERR; 177 1.32 uwe if (n < 0) 178 1.32 uwe return ERR; 179 1.32 uwe if (n > win->maxy - line) 180 1.32 uwe n = win->maxy - line; 181 1.32 uwe 182 1.13 blymn for (y = line; y < line + n; y++) { 183 1.13 blymn if (changed == 1) 184 1.27 blymn _cursesi_touchline_force(win, y, 0, 185 1.27 blymn (int) win->maxx - 1, 1); 186 1.13 blymn else { 187 1.25 roy wlp = win->alines[y]; 188 1.14 mycroft if (*wlp->firstchp >= win->ch_off && 189 1.14 mycroft *wlp->firstchp < win->maxx + win->ch_off) 190 1.14 mycroft *wlp->firstchp = win->maxx + win->ch_off; 191 1.14 mycroft if (*wlp->lastchp >= win->ch_off && 192 1.14 mycroft *wlp->lastchp < win->maxx + win->ch_off) 193 1.14 mycroft *wlp->lastchp = win->ch_off; 194 1.27 blymn wlp->flags &= ~(__ISDIRTY | __ISFORCED); 195 1.13 blymn } 196 1.13 blymn } 197 1.13 blymn 198 1.13 blymn return OK; 199 1.13 blymn } 200 1.27 blymn 201 1.34 blymn /* 202 1.34 blymn * Touch all the lines in a window. If force is set to 1 then screen 203 1.34 blymn * update optimisation will disabled to force the change out. 204 1.34 blymn */ 205 1.4 cgd int 206 1.34 blymn __touchwin(WINDOW *win, int force) 207 1.4 cgd { 208 1.24 blymn int y, maxy; 209 1.4 cgd 210 1.23 jdc __CTRACE(__CTRACE_LINE, "__touchwin: (%p)\n", win); 211 1.4 cgd maxy = win->maxy; 212 1.1 cgd for (y = 0; y < maxy; y++) 213 1.34 blymn _cursesi_touchline_force(win, y, 0, (int) win->maxx - 1, 214 1.34 blymn force); 215 1.30 roy return OK; 216 1.1 cgd } 217 1.1 cgd 218 1.3 mycroft int 219 1.15 mycroft __touchline(WINDOW *win, int y, int sx, int ex) 220 1.1 cgd { 221 1.30 roy 222 1.30 roy return _cursesi_touchline_force(win, y, sx, ex, 0); 223 1.27 blymn } 224 1.27 blymn 225 1.27 blymn /* 226 1.27 blymn * Touch line y on window win starting from column sx and ending at 227 1.27 blymn * column ex. If force is 1 then we mark this line as a forced update 228 1.27 blymn * which will bypass screen optimisation in the refresh code to rewrite 229 1.27 blymn * this line unconditionally (even if refresh thinks the screen matches 230 1.27 blymn * what is in the virtscr) 231 1.27 blymn */ 232 1.27 blymn static int 233 1.27 blymn _cursesi_touchline_force(WINDOW *win, int y, int sx, int ex, int force) 234 1.27 blymn { 235 1.30 roy 236 1.28 jdc __CTRACE(__CTRACE_LINE, "__touchline: (%p, %d, %d, %d, %d)\n", 237 1.28 jdc win, y, sx, ex, force); 238 1.23 jdc __CTRACE(__CTRACE_LINE, "__touchline: first = %d, last = %d\n", 239 1.25 roy *win->alines[y]->firstchp, *win->alines[y]->lastchp); 240 1.4 cgd sx += win->ch_off; 241 1.4 cgd ex += win->ch_off; 242 1.27 blymn win->alines[y]->flags |= __ISDIRTY; 243 1.27 blymn if (force == 1) 244 1.27 blymn win->alines[y]->flags |= __ISFORCED; 245 1.12 jdc /* firstchp/lastchp are shared between parent window and sub-window. */ 246 1.25 roy if (*win->alines[y]->firstchp > sx) 247 1.25 roy *win->alines[y]->firstchp = sx; 248 1.25 roy if (*win->alines[y]->lastchp < ex) 249 1.25 roy *win->alines[y]->lastchp = ex; 250 1.23 jdc __CTRACE(__CTRACE_LINE, "__touchline: first = %d, last = %d\n", 251 1.25 roy *win->alines[y]->firstchp, *win->alines[y]->lastchp); 252 1.30 roy return OK; 253 1.1 cgd } 254 1.26 drochner 255 1.26 drochner void 256 1.26 drochner wsyncup(WINDOW *win) 257 1.26 drochner { 258 1.26 drochner 259 1.35 blymn if (__predict_false(win == NULL)) 260 1.35 blymn return; 261 1.35 blymn 262 1.26 drochner do { 263 1.34 blymn __touchwin(win, 0); 264 1.26 drochner win = win->orig; 265 1.26 drochner } while (win); 266 1.26 drochner } 267 1.26 drochner 268 1.26 drochner void 269 1.26 drochner wsyncdown(WINDOW *win) 270 1.26 drochner { 271 1.35 blymn if (__predict_false(win == NULL)) 272 1.35 blymn return; 273 1.35 blymn 274 1.26 drochner WINDOW *w = win->orig; 275 1.26 drochner 276 1.26 drochner while (w) { 277 1.26 drochner if (is_wintouched(w)) { 278 1.34 blymn __touchwin(win, 0); 279 1.26 drochner break; 280 1.26 drochner } 281 1.26 drochner w = w->orig; 282 1.26 drochner } 283 1.26 drochner } 284