Home | History | Annotate | Line # | Download | only in libcurses
touchwin.c revision 1.34.4.1
      1  1.34.4.1  perseant /*	$NetBSD: touchwin.c,v 1.34.4.1 2025/08/02 05:54:47 perseant 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.34.4.1  perseant __RCSID("$NetBSD: touchwin.c,v 1.34.4.1 2025/08/02 05:54:47 perseant 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.34.4.1  perseant 	if (__predict_false(win == NULL))
     54  1.34.4.1  perseant 		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.34.4.1  perseant 	if (__predict_false(win == NULL))
     70  1.34.4.1  perseant 		return ERR;
     71  1.34.4.1  perseant 
     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.34.4.1  perseant 	if (__predict_false(win == NULL))
    115  1.34.4.1  perseant 		return FALSE;
    116  1.34.4.1  perseant 
    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.34.4.1  perseant 	if (__predict_false(win == NULL))
    173  1.34.4.1  perseant 		return FALSE;
    174  1.34.4.1  perseant 
    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.34.4.1  perseant 	if (__predict_false(win == NULL))
    260  1.34.4.1  perseant 		return;
    261  1.34.4.1  perseant 
    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.34.4.1  perseant 	if (__predict_false(win == NULL))
    272  1.34.4.1  perseant 		return;
    273  1.34.4.1  perseant 
    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