1 1.129 blymn /* $NetBSD: refresh.c,v 1.129 2024/12/23 02:58:04 blymn Exp $ */ 2 1.8 mikel 3 1.1 cgd /* 4 1.7 cgd * Copyright (c) 1981, 1993, 1994 5 1.5 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.58 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.8 mikel #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.8 mikel #if 0 35 1.7 cgd static char sccsid[] = "@(#)refresh.c 8.7 (Berkeley) 8/13/94"; 36 1.8 mikel #else 37 1.129 blymn __RCSID("$NetBSD: refresh.c,v 1.129 2024/12/23 02:58:04 blymn Exp $"); 38 1.8 mikel #endif 39 1.11 mrg #endif /* not lint */ 40 1.1 cgd 41 1.81 roy #include <poll.h> 42 1.38 matt #include <stdlib.h> 43 1.4 mycroft #include <string.h> 44 1.113 mrg #include <assert.h> 45 1.1 cgd 46 1.7 cgd #include "curses.h" 47 1.15 blymn #include "curses_private.h" 48 1.7 cgd 49 1.110 blymn static void domvcur(WINDOW *, int, int, int, int); 50 1.91 roy static void putattr(__LDATA *); 51 1.91 roy static void putattr_out(__LDATA *); 52 1.91 roy static int putch(__LDATA *, __LDATA *, int, int); 53 1.91 roy static int putchbr(__LDATA *, __LDATA *, __LDATA *, int, int); 54 1.65 blymn static int makech(int); 55 1.65 blymn static void quickch(void); 56 1.65 blymn static void scrolln(int, int, int, int, int); 57 1.65 blymn 58 1.86 roy static int _wnoutrefresh(WINDOW *, int, int, int, int, int, int); 59 1.65 blymn 60 1.95 uwe static int lineeq(__LDATA *, __LDATA *, size_t); 61 1.55 dsl 62 1.85 roy #define CHECK_INTERVAL 5 /* Change N lines before checking typeahead */ 63 1.85 roy 64 1.17 blymn #ifndef _CURSES_USE_MACROS 65 1.17 blymn 66 1.17 blymn /* 67 1.17 blymn * refresh -- 68 1.17 blymn * Make the current screen look like "stdscr" over the area covered by 69 1.17 blymn * stdscr. 70 1.17 blymn */ 71 1.17 blymn int 72 1.17 blymn refresh(void) 73 1.17 blymn { 74 1.83 roy 75 1.17 blymn return wrefresh(stdscr); 76 1.17 blymn } 77 1.17 blymn 78 1.17 blymn #endif 79 1.17 blymn 80 1.4 mycroft /* 81 1.23 jdc * wnoutrefresh -- 82 1.23 jdc * Add the contents of "win" to the virtual window. 83 1.23 jdc */ 84 1.23 jdc int 85 1.23 jdc wnoutrefresh(WINDOW *win) 86 1.23 jdc { 87 1.83 roy 88 1.115 rin __CTRACE(__CTRACE_REFRESH, 89 1.115 rin "wnoutrefresh: win %p, begy %d, begx %d, maxy %d, maxx %d\n", 90 1.115 rin win, win->begy, win->begx, win->maxy, win->maxx); 91 1.50 jdc 92 1.86 roy return _wnoutrefresh(win, 0, 0, win->begy, win->begx, 93 1.86 roy win->maxy, win->maxx); 94 1.44 blymn } 95 1.44 blymn 96 1.50 jdc /* 97 1.50 jdc * pnoutrefresh -- 98 1.50 jdc * Add the contents of "pad" to the virtual window. 99 1.50 jdc */ 100 1.50 jdc int 101 1.50 jdc pnoutrefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx, 102 1.83 roy int smaxy, int smaxx) 103 1.50 jdc { 104 1.50 jdc int pmaxy, pmaxx; 105 1.50 jdc 106 1.64 jdc __CTRACE(__CTRACE_REFRESH, "pnoutrefresh: pad %p, flags 0x%08x\n", 107 1.64 jdc pad, pad->flags); 108 1.64 jdc __CTRACE(__CTRACE_REFRESH, 109 1.64 jdc "pnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n", 110 1.64 jdc pbegy, pbegx, sbegy, sbegx, smaxy, smaxx); 111 1.50 jdc 112 1.129 blymn if (__predict_false(pad == NULL)) 113 1.129 blymn return ERR; 114 1.129 blymn 115 1.50 jdc /* SUS says if these are negative, they should be treated as zero */ 116 1.50 jdc if (pbegy < 0) 117 1.50 jdc pbegy = 0; 118 1.50 jdc if (pbegx < 0) 119 1.50 jdc pbegx = 0; 120 1.50 jdc if (sbegy < 0) 121 1.50 jdc sbegy = 0; 122 1.50 jdc if (sbegx < 0) 123 1.50 jdc sbegx = 0; 124 1.50 jdc 125 1.86 roy /* Calculate rectangle on pad - used by _wnoutrefresh */ 126 1.50 jdc pmaxy = pbegy + smaxy - sbegy + 1; 127 1.50 jdc pmaxx = pbegx + smaxx - sbegx + 1; 128 1.50 jdc 129 1.50 jdc /* Check rectangle fits in pad */ 130 1.50 jdc if (pmaxy > pad->maxy - pad->begy) 131 1.50 jdc pmaxy = pad->maxy - pad->begy; 132 1.50 jdc if (pmaxx > pad->maxx - pad->begx) 133 1.50 jdc pmaxx = pad->maxx - pad->begx; 134 1.65 blymn 135 1.50 jdc if (smaxy - sbegy < 0 || smaxx - sbegx < 0 ) 136 1.50 jdc return ERR; 137 1.50 jdc 138 1.86 roy return _wnoutrefresh(pad, 139 1.50 jdc pad->begy + pbegy, pad->begx + pbegx, pad->begy + sbegy, 140 1.50 jdc pad->begx + sbegx, pmaxy, pmaxx); 141 1.50 jdc } 142 1.44 blymn 143 1.44 blymn /* 144 1.86 roy * _wnoutrefresh -- 145 1.65 blymn * Does the grunt work for wnoutrefresh to the given screen. 146 1.50 jdc * Copies the part of the window given by the rectangle 147 1.50 jdc * (begy, begx) to (maxy, maxx) at screen position (wbegy, wbegx). 148 1.44 blymn */ 149 1.86 roy static int 150 1.86 roy _wnoutrefresh(WINDOW *win, int begy, int begx, int wbegy, int wbegx, 151 1.86 roy int maxy, int maxx) 152 1.44 blymn { 153 1.86 roy SCREEN *screen = win->screen; 154 1.79 blymn short sy, wy, wx, y_off, x_off, mx, dy_off, dx_off, endy; 155 1.105 uwe int newy, newx; 156 1.124 blymn #ifdef HAVE_WCHAR 157 1.124 blymn int i, tx; 158 1.124 blymn wchar_t ch; 159 1.124 blymn #endif 160 1.79 blymn __LINE *wlp, *vlp, *dwlp; 161 1.79 blymn WINDOW *sub_win, *orig, *swin, *dwin; 162 1.23 jdc 163 1.64 jdc __CTRACE(__CTRACE_REFRESH, "_wnoutrefresh: win %p, flags 0x%08x\n", 164 1.64 jdc win, win->flags); 165 1.64 jdc __CTRACE(__CTRACE_REFRESH, 166 1.64 jdc "_wnoutrefresh: (%d, %d), (%d, %d), (%d, %d)\n", 167 1.56 jdc begy, begx, wbegy, wbegx, maxy, maxx); 168 1.23 jdc 169 1.129 blymn if (__predict_false(win == NULL)) 170 1.129 blymn return ERR; 171 1.129 blymn 172 1.44 blymn if (screen->curwin) 173 1.57 jdc return OK; 174 1.57 jdc 175 1.79 blymn swin = dwin = win; 176 1.79 blymn if (win->flags & __ISDERWIN) 177 1.79 blymn swin = win->orig; 178 1.79 blymn 179 1.57 jdc /* 180 1.57 jdc * Recurse through any sub-windows, mark as dirty lines on the parent 181 1.57 jdc * window that are dirty on the sub-window and clear the dirty flag on 182 1.57 jdc * the sub-window. 183 1.57 jdc */ 184 1.79 blymn if (dwin->orig == 0) { 185 1.79 blymn orig = dwin; 186 1.79 blymn for (sub_win = dwin->nextp; sub_win != orig; 187 1.57 jdc sub_win = sub_win->nextp) { 188 1.79 blymn if (sub_win->flags & __ISDERWIN) 189 1.79 blymn continue; 190 1.64 jdc __CTRACE(__CTRACE_REFRESH, 191 1.64 jdc "wnout_refresh: win %p, sub_win %p\n", 192 1.57 jdc orig, sub_win); 193 1.57 jdc for (sy = 0; sy < sub_win->maxy; sy++) { 194 1.74 jdc if (sub_win->alines[sy]->flags & __ISDIRTY) { 195 1.71 roy orig->alines[sy + sub_win->begy - orig->begy]->flags 196 1.65 blymn |= __ISDIRTY; 197 1.71 roy sub_win->alines[sy]->flags 198 1.65 blymn &= ~__ISDIRTY; 199 1.57 jdc } 200 1.78 blymn if (sub_win->alines[sy]->flags & __ISFORCED) { 201 1.78 blymn orig->alines[sy + sub_win->begy - orig->begy]->flags 202 1.78 blymn |= __ISFORCED; 203 1.78 blymn sub_win->alines[sy]->flags 204 1.78 blymn &= ~__ISFORCED; 205 1.78 blymn } 206 1.57 jdc } 207 1.57 jdc } 208 1.57 jdc } 209 1.50 jdc 210 1.50 jdc /* Check that cursor position on "win" is valid for "__virtscr" */ 211 1.105 uwe newy = wbegy + dwin->cury - begy; 212 1.105 uwe newx = wbegx + dwin->curx - begx; 213 1.105 uwe if (begy <= dwin->cury && dwin->cury < maxy 214 1.105 uwe && 0 <= newy && newy < screen->__virtscr->maxy) 215 1.105 uwe screen->__virtscr->cury = newy; 216 1.105 uwe if (begx <= dwin->curx && dwin->curx < maxx 217 1.105 uwe && 0 <= newx && newx < screen->__virtscr->maxx) 218 1.105 uwe screen->__virtscr->curx = newx; 219 1.23 jdc 220 1.23 jdc /* Copy the window flags from "win" to "__virtscr" */ 221 1.79 blymn if (dwin->flags & __CLEAROK) { 222 1.79 blymn if (dwin->flags & __FULLWIN) 223 1.44 blymn screen->__virtscr->flags |= __CLEAROK; 224 1.79 blymn dwin->flags &= ~__CLEAROK; 225 1.33 mycroft } 226 1.44 blymn screen->__virtscr->flags &= ~__LEAVEOK; 227 1.79 blymn screen->__virtscr->flags |= dwin->flags; 228 1.23 jdc 229 1.79 blymn if ((dwin->flags & __ISDERWIN) != 0) 230 1.79 blymn endy = begy + maxy; 231 1.79 blymn else 232 1.79 blymn endy = maxy; 233 1.79 blymn 234 1.79 blymn for (wy = begy, y_off = wbegy, dy_off = 0; wy < endy && 235 1.83 roy y_off < screen->__virtscr->maxy; wy++, y_off++, dy_off++) 236 1.83 roy { 237 1.79 blymn wlp = swin->alines[wy]; 238 1.79 blymn dwlp = dwin->alines[dy_off]; 239 1.23 jdc #ifdef DEBUG 240 1.64 jdc __CTRACE(__CTRACE_REFRESH, 241 1.64 jdc "_wnoutrefresh: wy %d\tf %d\tl %d\tflags %x\n", 242 1.57 jdc wy, *wlp->firstchp, *wlp->lastchp, wlp->flags); 243 1.79 blymn 244 1.108 blymn char *_wintype; 245 1.108 blymn 246 1.108 blymn if ((dwin->flags & __ISDERWIN) != 0) 247 1.108 blymn _wintype = "derwin"; 248 1.108 blymn else 249 1.108 blymn _wintype = "dwin"; 250 1.108 blymn 251 1.108 blymn __CTRACE(__CTRACE_REFRESH, 252 1.115 rin "_wnoutrefresh: %s wy %d\tf %d\tl %d\tflags %x\n", 253 1.115 rin _wintype, dy_off, *dwlp->firstchp, *dwlp->lastchp, 254 1.115 rin dwlp->flags); 255 1.108 blymn __CTRACE(__CTRACE_REFRESH, 256 1.115 rin "_wnoutrefresh: %s maxx %d\tch_off %d wlp %p\n", 257 1.115 rin _wintype, dwin->maxx, dwin->ch_off, wlp); 258 1.23 jdc #endif 259 1.79 blymn if (((wlp->flags & (__ISDIRTY | __ISFORCED)) == 0) && 260 1.79 blymn ((dwlp->flags & (__ISDIRTY | __ISFORCED)) == 0)) 261 1.33 mycroft continue; 262 1.109 blymn __CTRACE(__CTRACE_REFRESH, 263 1.115 rin "_wnoutrefresh: line y_off %d (dy_off %d) is dirty\n", 264 1.115 rin y_off, dy_off); 265 1.109 blymn 266 1.109 blymn wlp = swin->alines[wy]; 267 1.71 roy vlp = screen->__virtscr->alines[y_off]; 268 1.33 mycroft 269 1.79 blymn if ((*wlp->firstchp < maxx + swin->ch_off && 270 1.79 blymn *wlp->lastchp >= swin->ch_off) || 271 1.79 blymn ((((dwin->flags & __ISDERWIN) != 0) && 272 1.79 blymn (*dwlp->firstchp < dwin->maxx + dwin->ch_off && 273 1.83 roy *dwlp->lastchp >= dwin->ch_off)))) 274 1.83 roy { 275 1.57 jdc /* Set start column */ 276 1.57 jdc wx = begx; 277 1.57 jdc x_off = wbegx; 278 1.79 blymn dx_off = 0; 279 1.79 blymn /* 280 1.79 blymn * if a derwin then source change pointers aren't 281 1.79 blymn * relevant. 282 1.79 blymn */ 283 1.79 blymn if ((dwin->flags & __ISDERWIN) != 0) 284 1.79 blymn mx = wx + maxx; 285 1.79 blymn else { 286 1.79 blymn if (*wlp->firstchp - swin->ch_off > 0) { 287 1.79 blymn wx += *wlp->firstchp - swin->ch_off; 288 1.79 blymn x_off += *wlp->firstchp - swin->ch_off; 289 1.79 blymn } 290 1.79 blymn mx = maxx; 291 1.79 blymn if (mx > *wlp->lastchp - swin->ch_off + 1) 292 1.79 blymn mx = *dwlp->lastchp - dwin->ch_off + 1; 293 1.87 roy if (x_off + (mx - wx) > screen->__virtscr->maxx) 294 1.87 roy mx -= (x_off + maxx) - 295 1.87 roy screen->__virtscr->maxx; 296 1.79 blymn } 297 1.79 blymn 298 1.23 jdc /* Copy line from "win" to "__virtscr". */ 299 1.57 jdc while (wx < mx) { 300 1.64 jdc __CTRACE(__CTRACE_REFRESH, 301 1.64 jdc "_wnoutrefresh: copy from %d, " 302 1.124 blymn "%d to %d, %d: '%s', 0x%x, 0x%x", 303 1.77 jdc wy, wx, y_off, x_off, 304 1.77 jdc unctrl(wlp->line[wx].ch), 305 1.124 blymn wlp->line[wx].attr, wlp->line[wx].cflags); 306 1.115 rin __CTRACE(__CTRACE_REFRESH, 307 1.124 blymn " (curdest %s, 0x%x, 0x%x)", 308 1.109 blymn unctrl(vlp->line[x_off].ch), 309 1.124 blymn vlp->line[x_off].attr, 310 1.124 blymn vlp->line[x_off].cflags); 311 1.63 jdc /* Copy character */ 312 1.63 jdc vlp->line[x_off].ch = wlp->line[wx].ch; 313 1.63 jdc /* Copy attributes */ 314 1.33 mycroft vlp->line[x_off].attr = wlp->line[wx].attr; 315 1.124 blymn /* Copy character flags */ 316 1.124 blymn vlp->line[x_off].cflags = wlp->line[wx].cflags; 317 1.118 blymn #ifdef HAVE_WCHAR 318 1.118 blymn vlp->line[x_off].wcols = wlp->line[wx].wcols; 319 1.124 blymn 320 1.124 blymn ch = wlp->line[wx].ch; 321 1.124 blymn for (tx = x_off + 1, i = wlp->line[wx].wcols - 1; 322 1.124 blymn i > 0; i--, tx++) { 323 1.124 blymn vlp->line[tx].ch = ch; 324 1.124 blymn vlp->line[tx].wcols = i; 325 1.124 blymn vlp->line[tx].cflags = 326 1.124 blymn CA_CONTINUATION; 327 1.124 blymn } 328 1.118 blymn #endif /* HAVE_WCHAR */ 329 1.79 blymn if (win->flags & __ISDERWIN) { 330 1.79 blymn dwlp->line[dx_off].ch = 331 1.79 blymn wlp->line[wx].ch; 332 1.83 roy dwlp->line[dx_off].attr = 333 1.79 blymn wlp->line[wx].attr; 334 1.124 blymn dwlp->line[dx_off].cflags = 335 1.124 blymn wlp->line[wx].cflags; 336 1.118 blymn #ifdef HAVE_WCHAR 337 1.118 blymn dwlp->line[dx_off].wcols = 338 1.118 blymn wlp->line[wx].wcols; 339 1.124 blymn 340 1.124 blymn for (tx = dx_off + 1, i = wlp->line[wx].wcols - 1; 341 1.124 blymn i > 0; i--, tx++) { 342 1.124 blymn dwlp->line[tx].ch = ch; 343 1.124 blymn dwlp->line[tx].wcols = i; 344 1.124 blymn dwlp->line[tx].cflags = 345 1.124 blymn CA_CONTINUATION; 346 1.124 blymn } 347 1.118 blymn #endif /* HAVE_WCHAR */ 348 1.79 blymn } 349 1.79 blymn 350 1.65 blymn #ifdef HAVE_WCHAR 351 1.119 blymn if (wlp->line[wx].ch == win->bch) { 352 1.65 blymn vlp->line[x_off].ch = win->bch; 353 1.118 blymn vlp->line[x_off].wcols = win->wcols; 354 1.124 blymn vlp->line[x_off].cflags = CA_BACKGROUND; 355 1.65 blymn if (_cursesi_copy_nsp(win->bnsp, 356 1.65 blymn &vlp->line[x_off]) 357 1.65 blymn == ERR) 358 1.65 blymn return ERR; 359 1.79 blymn if (win->flags & __ISDERWIN) { 360 1.79 blymn dwlp->line[dx_off].ch = 361 1.79 blymn win->bch; 362 1.118 blymn dwlp->line[dx_off].wcols = 363 1.118 blymn win->wcols; 364 1.124 blymn dwlp->line[dx_off].cflags = 365 1.124 blymn wlp->line[wx].cflags; 366 1.79 blymn if (_cursesi_copy_nsp(win->bnsp, 367 1.79 blymn &dwlp->line[dx_off]) 368 1.83 roy == ERR) 369 1.79 blymn return ERR; 370 1.79 blymn } 371 1.65 blymn } 372 1.65 blymn #endif /* HAVE_WCHAR */ 373 1.119 blymn __CTRACE(__CTRACE_REFRESH, " = '%s', 0x%x\n", 374 1.77 jdc unctrl(vlp->line[x_off].ch), 375 1.77 jdc vlp->line[x_off].attr); 376 1.124 blymn #ifdef HAVE_WCHAR 377 1.124 blymn x_off += wlp->line[wx].wcols; 378 1.124 blymn dx_off += wlp->line[wx].wcols; 379 1.124 blymn wx += wlp->line[wx].wcols; 380 1.124 blymn #else 381 1.124 blymn wx++; 382 1.57 jdc x_off++; 383 1.79 blymn dx_off++; 384 1.124 blymn #endif /* HAVE_WCHAR */ 385 1.23 jdc } 386 1.23 jdc 387 1.23 jdc /* Set flags on "__virtscr" and unset on "win". */ 388 1.33 mycroft if (wlp->flags & __ISPASTEOL) 389 1.33 mycroft vlp->flags |= __ISPASTEOL; 390 1.23 jdc else 391 1.33 mycroft vlp->flags &= ~__ISPASTEOL; 392 1.33 mycroft if (wlp->flags & __ISDIRTY) 393 1.33 mycroft vlp->flags |= __ISDIRTY; 394 1.78 blymn if (wlp->flags & __ISFORCED) 395 1.78 blymn vlp->flags |= __ISFORCED; 396 1.23 jdc 397 1.23 jdc #ifdef DEBUG 398 1.64 jdc __CTRACE(__CTRACE_REFRESH, 399 1.64 jdc "win: firstch = %d, lastch = %d\n", 400 1.33 mycroft *wlp->firstchp, *wlp->lastchp); 401 1.79 blymn if (win->flags & __ISDERWIN) { 402 1.79 blymn __CTRACE(__CTRACE_REFRESH, 403 1.79 blymn "derwin: fistch = %d, lastch = %d\n", 404 1.79 blymn *dwlp->firstchp, *dwlp->lastchp); 405 1.79 blymn } 406 1.23 jdc #endif 407 1.23 jdc /* Set change pointers on "__virtscr". */ 408 1.33 mycroft if (*vlp->firstchp > 409 1.78 blymn *wlp->firstchp + wbegx - win->ch_off) 410 1.78 blymn *vlp->firstchp = 411 1.78 blymn *wlp->firstchp + wbegx - win->ch_off; 412 1.33 mycroft if (*vlp->lastchp < 413 1.78 blymn *wlp->lastchp + wbegx - win->ch_off) 414 1.78 blymn *vlp->lastchp = 415 1.78 blymn *wlp->lastchp + wbegx - win->ch_off; 416 1.79 blymn 417 1.79 blymn if (win->flags & __ISDERWIN) { 418 1.83 roy if (*vlp->firstchp > 419 1.83 roy *dwlp->firstchp + wbegx - dwin->ch_off) 420 1.83 roy { 421 1.79 blymn *vlp->firstchp = 422 1.79 blymn *dwlp->firstchp + wbegx 423 1.79 blymn - dwin->ch_off; 424 1.79 blymn vlp->flags |= __ISDIRTY; 425 1.79 blymn } 426 1.79 blymn 427 1.79 blymn if (*vlp->lastchp < 428 1.83 roy *dwlp->lastchp + wbegx - dwin->ch_off) 429 1.83 roy { 430 1.79 blymn *vlp->lastchp = *dwlp->lastchp 431 1.79 blymn + wbegx - dwin->ch_off; 432 1.79 blymn vlp->flags |= __ISDIRTY; 433 1.79 blymn } 434 1.79 blymn } 435 1.79 blymn 436 1.64 jdc __CTRACE(__CTRACE_REFRESH, 437 1.64 jdc "__virtscr: firstch = %d, lastch = %d\n", 438 1.33 mycroft *vlp->firstchp, *vlp->lastchp); 439 1.50 jdc /* 440 1.78 blymn * Unset change pointers only if a window and we 441 1.78 blymn * are not forcing a redraw. A pad can be displayed 442 1.78 blymn * again without any of the contents changing. 443 1.50 jdc */ 444 1.124 blymn if (!((win->flags & __ISPAD)) || 445 1.83 roy ((wlp->flags & __ISFORCED) == __ISFORCED)) 446 1.83 roy { 447 1.50 jdc /* Set change pointers on "win". */ 448 1.50 jdc if (*wlp->firstchp >= win->ch_off) 449 1.50 jdc *wlp->firstchp = maxx + win->ch_off; 450 1.50 jdc if (*wlp->lastchp < maxx + win->ch_off) 451 1.50 jdc *wlp->lastchp = win->ch_off; 452 1.57 jdc if ((*wlp->lastchp < *wlp->firstchp) || 453 1.57 jdc (*wlp->firstchp >= maxx + win->ch_off) || 454 1.57 jdc (*wlp->lastchp <= win->ch_off)) { 455 1.64 jdc __CTRACE(__CTRACE_REFRESH, 456 1.64 jdc "_wnoutrefresh: " 457 1.64 jdc "line %d notdirty\n", wy); 458 1.80 jdc wlp->flags &= ~(__ISDIRTY | __ISFORCED); 459 1.50 jdc } 460 1.23 jdc } 461 1.23 jdc } 462 1.23 jdc } 463 1.55 dsl return OK; 464 1.23 jdc } 465 1.23 jdc 466 1.23 jdc /* 467 1.4 mycroft * wrefresh -- 468 1.50 jdc * Make the current screen look like "win" over the area covered by 469 1.4 mycroft * win. 470 1.4 mycroft */ 471 1.4 mycroft int 472 1.17 blymn wrefresh(WINDOW *win) 473 1.1 cgd { 474 1.44 blymn int retval; 475 1.79 blymn int pbegx, pbegy; 476 1.45 blymn 477 1.64 jdc __CTRACE(__CTRACE_REFRESH, "wrefresh: win %p\n", win); 478 1.50 jdc 479 1.129 blymn if (__predict_false(win == NULL)) 480 1.129 blymn return ERR; 481 1.129 blymn 482 1.44 blymn _cursesi_screen->curwin = (win == _cursesi_screen->curscr); 483 1.79 blymn if (!_cursesi_screen->curwin) { 484 1.79 blymn pbegx = pbegy = 0; 485 1.79 blymn if ((win->flags & __ISDERWIN) == __ISDERWIN) { 486 1.79 blymn pbegx = win->derx; 487 1.79 blymn pbegy = win->dery; 488 1.79 blymn __CTRACE(__CTRACE_REFRESH, "wrefresh: derwin, begy = %d, begx = %x\n", 489 1.79 blymn pbegy, pbegx); 490 1.79 blymn } 491 1.86 roy retval = _wnoutrefresh(win, pbegy, pbegx, win->begy, win->begx, 492 1.86 roy win->maxy, win->maxx); 493 1.79 blymn } else 494 1.23 jdc retval = OK; 495 1.23 jdc if (retval == OK) { 496 1.23 jdc retval = doupdate(); 497 1.55 dsl if (!(win->flags & __LEAVEOK)) { 498 1.24 jdc win->cury = max(0, curscr->cury - win->begy); 499 1.24 jdc win->curx = max(0, curscr->curx - win->begx); 500 1.24 jdc } 501 1.23 jdc } 502 1.43 blymn _cursesi_screen->curwin = 0; 503 1.83 roy return retval; 504 1.50 jdc } 505 1.50 jdc 506 1.50 jdc /* 507 1.50 jdc * prefresh -- 508 1.50 jdc * Make the current screen look like "pad" over the area coverd by 509 1.50 jdc * the specified area of pad. 510 1.50 jdc */ 511 1.50 jdc int 512 1.50 jdc prefresh(WINDOW *pad, int pbegy, int pbegx, int sbegy, int sbegx, 513 1.65 blymn int smaxy, int smaxx) 514 1.50 jdc { 515 1.50 jdc int retval; 516 1.50 jdc 517 1.64 jdc __CTRACE(__CTRACE_REFRESH, "prefresh: pad %p, flags 0x%08x\n", 518 1.64 jdc pad, pad->flags); 519 1.129 blymn 520 1.129 blymn if (__predict_false(pad == NULL)) 521 1.129 blymn return ERR; 522 1.129 blymn 523 1.59 jdc /* Retain values in case pechochar() is called. */ 524 1.59 jdc pad->pbegy = pbegy; 525 1.59 jdc pad->pbegx = pbegx; 526 1.59 jdc pad->sbegy = sbegy; 527 1.59 jdc pad->sbegx = sbegx; 528 1.59 jdc pad->smaxy = smaxy; 529 1.59 jdc pad->smaxx = smaxx; 530 1.50 jdc 531 1.50 jdc /* Use pnoutrefresh() to avoid duplicating code here */ 532 1.50 jdc retval = pnoutrefresh(pad, pbegy, pbegx, sbegy, sbegx, smaxy, smaxx); 533 1.50 jdc if (retval == OK) { 534 1.50 jdc retval = doupdate(); 535 1.55 dsl if (!(pad->flags & __LEAVEOK)) { 536 1.103 uwe pad->cury = max(0, pbegy + (curscr->cury - sbegy)); 537 1.103 uwe pad->curx = max(0, pbegx + (curscr->curx - sbegx)); 538 1.50 jdc } 539 1.50 jdc } 540 1.83 roy return retval; 541 1.23 jdc } 542 1.23 jdc 543 1.23 jdc /* 544 1.23 jdc * doupdate -- 545 1.23 jdc * Make the current screen look like the virtual window "__virtscr". 546 1.23 jdc */ 547 1.23 jdc int 548 1.23 jdc doupdate(void) 549 1.23 jdc { 550 1.23 jdc WINDOW *win; 551 1.78 blymn __LINE *wlp, *vlp; 552 1.23 jdc short wy; 553 1.85 roy int dnum, was_cleared, changed; 554 1.9 phil 555 1.9 phil /* Check if we need to restart ... */ 556 1.43 blymn if (_cursesi_screen->endwin) 557 1.9 phil __restartwin(); 558 1.7 cgd 559 1.43 blymn if (_cursesi_screen->curwin) 560 1.23 jdc win = curscr; 561 1.23 jdc else 562 1.44 blymn win = _cursesi_screen->__virtscr; 563 1.23 jdc 564 1.4 mycroft /* Initialize loop parameters. */ 565 1.43 blymn _cursesi_screen->ly = curscr->cury; 566 1.43 blymn _cursesi_screen->lx = curscr->curx; 567 1.1 cgd wy = 0; 568 1.1 cgd 569 1.65 blymn if (!_cursesi_screen->curwin) { 570 1.5 cgd for (wy = 0; wy < win->maxy; wy++) { 571 1.71 roy wlp = win->alines[wy]; 572 1.116 rin if (wlp->flags & __ISDIRTY) 573 1.116 rin wlp->hash = __hash_line(wlp->line, win->maxx); 574 1.5 cgd } 575 1.65 blymn } 576 1.5 cgd 577 1.78 blymn was_cleared = 0; 578 1.43 blymn if ((win->flags & __CLEAROK) || (curscr->flags & __CLEAROK) || 579 1.83 roy _cursesi_screen->curwin) 580 1.83 roy { 581 1.23 jdc if (curscr->wattr & __COLOR) 582 1.23 jdc __unsetattr(0); 583 1.72 roy tputs(clear_screen, 0, __cputchar); 584 1.43 blymn _cursesi_screen->ly = 0; 585 1.43 blymn _cursesi_screen->lx = 0; 586 1.43 blymn if (!_cursesi_screen->curwin) { 587 1.23 jdc curscr->flags &= ~__CLEAROK; 588 1.23 jdc curscr->cury = 0; 589 1.23 jdc curscr->curx = 0; 590 1.23 jdc werase(curscr); 591 1.1 cgd } 592 1.119 blymn __touchwin(win, 0); 593 1.5 cgd win->flags &= ~__CLEAROK; 594 1.78 blymn /* note we cleared for later */ 595 1.78 blymn was_cleared = 1; 596 1.1 cgd } 597 1.72 roy if (!cursor_address) { 598 1.5 cgd if (win->curx != 0) 599 1.39 itojun __cputchar('\n'); 600 1.43 blymn if (!_cursesi_screen->curwin) 601 1.1 cgd werase(curscr); 602 1.1 cgd } 603 1.64 jdc __CTRACE(__CTRACE_REFRESH, "doupdate: (%p): curwin = %d\n", win, 604 1.65 blymn _cursesi_screen->curwin); 605 1.64 jdc __CTRACE(__CTRACE_REFRESH, "doupdate: \tfirstch\tlastch\n"); 606 1.5 cgd 607 1.43 blymn if (!_cursesi_screen->curwin) { 608 1.5 cgd /* 609 1.5 cgd * Invoke quickch() only if more than a quarter of the lines 610 1.5 cgd * in the window are dirty. 611 1.5 cgd */ 612 1.5 cgd for (wy = 0, dnum = 0; wy < win->maxy; wy++) 613 1.71 roy if (win->alines[wy]->flags & __ISDIRTY) 614 1.5 cgd dnum++; 615 1.5 cgd if (!__noqch && dnum > (int) win->maxy / 4) 616 1.23 jdc quickch(); 617 1.5 cgd } 618 1.5 cgd 619 1.5 cgd #ifdef DEBUG 620 1.11 mrg { 621 1.11 mrg int i, j; 622 1.11 mrg 623 1.64 jdc __CTRACE(__CTRACE_REFRESH, 624 1.64 jdc "#####################################\n"); 625 1.65 blymn __CTRACE(__CTRACE_REFRESH, 626 1.65 blymn "stdscr(%p)-curscr(%p)-__virtscr(%p)\n", 627 1.65 blymn stdscr, curscr, _cursesi_screen->__virtscr); 628 1.5 cgd for (i = 0; i < curscr->maxy; i++) { 629 1.124 blymn __CTRACE(__CTRACE_REFRESH, "curscr: %d:", i); 630 1.64 jdc __CTRACE(__CTRACE_REFRESH, " 0x%x \n", 631 1.71 roy curscr->alines[i]->hash); 632 1.7 cgd for (j = 0; j < curscr->maxx; j++) 633 1.64 jdc __CTRACE(__CTRACE_REFRESH, "%c", 634 1.71 roy curscr->alines[i]->line[j].ch); 635 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 636 1.64 jdc __CTRACE(__CTRACE_REFRESH, " attr:"); 637 1.7 cgd for (j = 0; j < curscr->maxx; j++) 638 1.64 jdc __CTRACE(__CTRACE_REFRESH, " %x", 639 1.71 roy curscr->alines[i]->line[j].attr); 640 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 641 1.118 blymn #ifdef HAVE_WCHAR 642 1.118 blymn __CTRACE(__CTRACE_REFRESH, " wcols:"); 643 1.118 blymn for (j = 0; j < curscr->maxx; j++) 644 1.118 blymn __CTRACE(__CTRACE_REFRESH, " %d", 645 1.118 blymn curscr->alines[i]->line[j].wcols); 646 1.118 blymn __CTRACE(__CTRACE_REFRESH, "\n"); 647 1.124 blymn 648 1.124 blymn __CTRACE(__CTRACE_REFRESH, " cflags:"); 649 1.124 blymn for (j = 0; j < curscr->maxx; j++) 650 1.124 blymn __CTRACE(__CTRACE_REFRESH, " 0x%x", 651 1.124 blymn curscr->alines[i]->line[j].cflags); 652 1.124 blymn __CTRACE(__CTRACE_REFRESH, "\n"); 653 1.118 blymn #endif /* HAVE_WCHAR */ 654 1.124 blymn __CTRACE(__CTRACE_REFRESH, "win %p: %d:", win, i); 655 1.64 jdc __CTRACE(__CTRACE_REFRESH, " 0x%x \n", 656 1.71 roy win->alines[i]->hash); 657 1.64 jdc __CTRACE(__CTRACE_REFRESH, " 0x%x ", 658 1.71 roy win->alines[i]->flags); 659 1.23 jdc for (j = 0; j < win->maxx; j++) 660 1.64 jdc __CTRACE(__CTRACE_REFRESH, "%c", 661 1.71 roy win->alines[i]->line[j].ch); 662 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 663 1.64 jdc __CTRACE(__CTRACE_REFRESH, " attr:"); 664 1.23 jdc for (j = 0; j < win->maxx; j++) 665 1.64 jdc __CTRACE(__CTRACE_REFRESH, " %x", 666 1.71 roy win->alines[i]->line[j].attr); 667 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 668 1.65 blymn #ifdef HAVE_WCHAR 669 1.118 blymn __CTRACE(__CTRACE_REFRESH, " wcols:"); 670 1.118 blymn for (j = 0; j < win->maxx; j++) 671 1.118 blymn __CTRACE(__CTRACE_REFRESH, " %d", 672 1.118 blymn win->alines[i]->line[j].wcols); 673 1.118 blymn __CTRACE(__CTRACE_REFRESH, "\n"); 674 1.124 blymn __CTRACE(__CTRACE_REFRESH, " cflags:"); 675 1.124 blymn for (j = 0; j < win->maxx; j++) 676 1.124 blymn __CTRACE(__CTRACE_REFRESH, " 0x%x", 677 1.124 blymn win->alines[i]->line[j].cflags); 678 1.124 blymn __CTRACE(__CTRACE_REFRESH, "\n"); 679 1.65 blymn __CTRACE(__CTRACE_REFRESH, " nsp:"); 680 1.65 blymn for (j = 0; j < curscr->maxx; j++) 681 1.65 blymn __CTRACE(__CTRACE_REFRESH, " %p", 682 1.71 roy win->alines[i]->line[j].nsp); 683 1.65 blymn __CTRACE(__CTRACE_REFRESH, "\n"); 684 1.65 blymn __CTRACE(__CTRACE_REFRESH, " bnsp:"); 685 1.65 blymn for (j = 0; j < curscr->maxx; j++) 686 1.65 blymn __CTRACE(__CTRACE_REFRESH, " %p", 687 1.65 blymn win->bnsp); 688 1.65 blymn __CTRACE(__CTRACE_REFRESH, "\n"); 689 1.65 blymn #endif /* HAVE_WCHAR */ 690 1.5 cgd } 691 1.11 mrg } 692 1.65 blymn #endif /* DEBUG */ 693 1.5 cgd 694 1.85 roy changed = 0; 695 1.5 cgd for (wy = 0; wy < win->maxy; wy++) { 696 1.71 roy wlp = win->alines[wy]; 697 1.78 blymn vlp = _cursesi_screen->__virtscr->alines[win->begy + wy]; 698 1.114 rin /* XXX: remove this */ 699 1.64 jdc __CTRACE(__CTRACE_REFRESH, 700 1.64 jdc "doupdate: wy %d\tf: %d\tl:%d\tflags %x\n", 701 1.64 jdc wy, *wlp->firstchp, *wlp->lastchp, wlp->flags); 702 1.43 blymn if (!_cursesi_screen->curwin) 703 1.71 roy curscr->alines[wy]->hash = wlp->hash; 704 1.84 roy if (wlp->flags & __ISDIRTY || wlp->flags & __ISFORCED) { 705 1.65 blymn __CTRACE(__CTRACE_REFRESH, 706 1.65 blymn "doupdate: [ISDIRTY]wy:%d\tf:%d\tl:%d\n", wy, 707 1.65 blymn *wlp->firstchp, *wlp->lastchp); 708 1.78 blymn /* 709 1.83 roy * We have just cleared so don't force an update 710 1.128 msaitoh * otherwise we spray needless blanks to a cleared 711 1.119 blymn * screen. That is, unless, we are using color, 712 1.119 blymn * in this case we need to force the background 713 1.119 blymn * color to default. 714 1.83 roy */ 715 1.119 blymn if ((was_cleared == 1) && (__using_color == 0)) 716 1.124 blymn win->alines[wy]->flags &= ~ 0L; 717 1.124 blymn /*if ((was_cleared == 1) && (__using_color == 0)) 718 1.124 blymn win->alines[wy]->flags &= ~__ISFORCED;*/ 719 1.78 blymn 720 1.23 jdc if (makech(wy) == ERR) 721 1.83 roy return ERR; 722 1.1 cgd else { 723 1.33 mycroft if (*wlp->firstchp >= 0) 724 1.33 mycroft *wlp->firstchp = win->maxx; 725 1.33 mycroft if (*wlp->lastchp < win->maxx) 726 1.78 blymn *wlp->lastchp = win->ch_off; 727 1.33 mycroft if (*wlp->lastchp < *wlp->firstchp) { 728 1.64 jdc __CTRACE(__CTRACE_REFRESH, 729 1.64 jdc "doupdate: line %d notdirty\n", wy); 730 1.78 blymn wlp->flags &= ~(__ISDIRTY | __ISFORCED); 731 1.5 cgd } 732 1.85 roy 733 1.85 roy /* Check if we have input after 734 1.85 roy * changing N lines. */ 735 1.85 roy if (_cursesi_screen->checkfd != -1 && 736 1.85 roy ++changed == CHECK_INTERVAL) 737 1.85 roy { 738 1.85 roy struct pollfd fds[1]; 739 1.85 roy 740 1.85 roy /* If we have input, abort. */ 741 1.85 roy fds[0].fd = _cursesi_screen->checkfd; 742 1.85 roy fds[0].events = POLLIN; 743 1.85 roy if (poll(fds, 1, 0) > 0) 744 1.85 roy goto cleanup; 745 1.85 roy changed = 0; 746 1.85 roy } 747 1.1 cgd } 748 1.78 blymn } 749 1.78 blymn 750 1.78 blymn /* 751 1.78 blymn * virtscr is now synced for the line, unset the change 752 1.78 blymn * pointers. 753 1.78 blymn */ 754 1.78 blymn if (*vlp->firstchp >= 0) 755 1.78 blymn *vlp->firstchp = _cursesi_screen->__virtscr->maxx; 756 1.78 blymn if (*vlp->lastchp <= _cursesi_screen->__virtscr->maxx) 757 1.78 blymn *vlp->lastchp = 0; 758 1.5 cgd 759 1.65 blymn __CTRACE(__CTRACE_REFRESH, "\t%d\t%d\n", 760 1.64 jdc *wlp->firstchp, *wlp->lastchp); 761 1.1 cgd } 762 1.7 cgd 763 1.64 jdc __CTRACE(__CTRACE_REFRESH, "doupdate: ly=%d, lx=%d\n", 764 1.64 jdc _cursesi_screen->ly, _cursesi_screen->lx); 765 1.1 cgd 766 1.43 blymn if (_cursesi_screen->curwin) 767 1.84 roy domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx, 768 1.70 yamt win->cury, win->curx); 769 1.1 cgd else { 770 1.5 cgd if (win->flags & __LEAVEOK) { 771 1.43 blymn curscr->cury = _cursesi_screen->ly; 772 1.43 blymn curscr->curx = _cursesi_screen->lx; 773 1.4 mycroft } else { 774 1.84 roy domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx, 775 1.43 blymn win->cury, win->curx); 776 1.23 jdc curscr->cury = win->cury; 777 1.23 jdc curscr->curx = win->curx; 778 1.1 cgd } 779 1.1 cgd } 780 1.23 jdc 781 1.81 roy cleanup: 782 1.28 mycroft /* Don't leave the screen with attributes set. */ 783 1.28 mycroft __unsetattr(0); 784 1.119 blymn __do_color_init = 0; 785 1.65 blymn #ifdef DEBUG 786 1.65 blymn #ifdef HAVE_WCHAR 787 1.65 blymn { 788 1.65 blymn int i, j; 789 1.65 blymn 790 1.65 blymn __CTRACE(__CTRACE_REFRESH, 791 1.65 blymn "***********after*****************\n"); 792 1.65 blymn __CTRACE(__CTRACE_REFRESH, 793 1.65 blymn "stdscr(%p)-curscr(%p)-__virtscr(%p)\n", 794 1.65 blymn stdscr, curscr, _cursesi_screen->__virtscr); 795 1.65 blymn for (i = 0; i < curscr->maxy; i++) { 796 1.65 blymn for (j = 0; j < curscr->maxx; j++) 797 1.65 blymn __CTRACE(__CTRACE_REFRESH, 798 1.124 blymn "[%d,%d](%x,%x,%d,%x,%p)-(%x,%x,%d,%x,%p)\n", 799 1.65 blymn i, j, 800 1.71 roy curscr->alines[i]->line[j].ch, 801 1.71 roy curscr->alines[i]->line[j].attr, 802 1.118 blymn curscr->alines[i]->line[j].wcols, 803 1.124 blymn curscr->alines[i]->line[j].cflags, 804 1.71 roy curscr->alines[i]->line[j].nsp, 805 1.71 roy _cursesi_screen->__virtscr->alines[i]->line[j].ch, 806 1.71 roy _cursesi_screen->__virtscr->alines[i]->line[j].attr, 807 1.118 blymn _cursesi_screen->__virtscr->alines[i]->line[j].wcols, 808 1.124 blymn _cursesi_screen->__virtscr->alines[i]->line[j].cflags, 809 1.71 roy _cursesi_screen->__virtscr->alines[i]->line[j].nsp); 810 1.65 blymn } 811 1.65 blymn } 812 1.65 blymn #endif /* HAVE_WCHAR */ 813 1.65 blymn #endif /* DEBUG */ 814 1.60 christos return fflush(_cursesi_screen->outfd) == EOF ? ERR : OK; 815 1.1 cgd } 816 1.1 cgd 817 1.91 roy static void 818 1.91 roy putattr(__LDATA *nsp) 819 1.91 roy { 820 1.91 roy attr_t off, on; 821 1.91 roy 822 1.91 roy __CTRACE(__CTRACE_REFRESH, 823 1.119 blymn "putattr: have attr %08x, need attr %08x\n", 824 1.91 roy curscr->wattr 825 1.91 roy #ifndef HAVE_WCHAR 826 1.91 roy & __ATTRIBUTES 827 1.91 roy #else 828 1.91 roy & WA_ATTRIBUTES 829 1.91 roy #endif 830 1.91 roy , nsp->attr 831 1.91 roy #ifndef HAVE_WCHAR 832 1.91 roy & __ATTRIBUTES 833 1.91 roy #else 834 1.91 roy & WA_ATTRIBUTES 835 1.91 roy #endif 836 1.91 roy ); 837 1.91 roy 838 1.91 roy off = (~nsp->attr & curscr->wattr) 839 1.91 roy #ifndef HAVE_WCHAR 840 1.91 roy & __ATTRIBUTES 841 1.91 roy #else 842 1.91 roy & WA_ATTRIBUTES 843 1.91 roy #endif 844 1.91 roy ; 845 1.91 roy 846 1.91 roy /* 847 1.91 roy * Unset attributes as appropriate. Unset first 848 1.91 roy * so that the relevant attributes can be reset 849 1.91 roy * (because 'me' unsets 'mb', 'md', 'mh', 'mk', 850 1.91 roy * 'mp' and 'mr'). Check to see if we also turn off 851 1.91 roy * standout, attributes and colour. 852 1.91 roy */ 853 1.91 roy if (off & __TERMATTR && exit_attribute_mode != NULL) { 854 1.91 roy tputs(exit_attribute_mode, 0, __cputchar); 855 1.91 roy curscr->wattr &= __mask_me; 856 1.91 roy off &= __mask_me; 857 1.91 roy } 858 1.91 roy 859 1.91 roy /* 860 1.91 roy * Exit underscore mode if appropriate. 861 1.91 roy * Check to see if we also turn off standout, 862 1.91 roy * attributes and colour. 863 1.91 roy */ 864 1.91 roy if (off & __UNDERSCORE && exit_underline_mode != NULL) { 865 1.91 roy tputs(exit_underline_mode, 0, __cputchar); 866 1.91 roy curscr->wattr &= __mask_ue; 867 1.91 roy off &= __mask_ue; 868 1.91 roy } 869 1.91 roy 870 1.91 roy /* 871 1.91 roy * Exit standout mode as appropriate. 872 1.91 roy * Check to see if we also turn off underscore, 873 1.91 roy * attributes and colour. 874 1.91 roy * XXX 875 1.91 roy * Should use uc if so/se not available. 876 1.91 roy */ 877 1.91 roy if (off & __STANDOUT && exit_standout_mode != NULL) { 878 1.91 roy tputs(exit_standout_mode, 0, __cputchar); 879 1.91 roy curscr->wattr &= __mask_se; 880 1.91 roy off &= __mask_se; 881 1.91 roy } 882 1.91 roy 883 1.91 roy if (off & __ALTCHARSET && exit_alt_charset_mode != NULL) { 884 1.91 roy tputs(exit_alt_charset_mode, 0, __cputchar); 885 1.91 roy curscr->wattr &= ~__ALTCHARSET; 886 1.91 roy } 887 1.91 roy 888 1.91 roy /* Set/change colour as appropriate. */ 889 1.91 roy if (__using_color) 890 1.91 roy __set_color(curscr, nsp->attr & __COLOR); 891 1.91 roy 892 1.91 roy on = (nsp->attr & ~curscr->wattr) 893 1.91 roy #ifndef HAVE_WCHAR 894 1.91 roy & __ATTRIBUTES 895 1.91 roy #else 896 1.91 roy & WA_ATTRIBUTES 897 1.91 roy #endif 898 1.91 roy ; 899 1.91 roy 900 1.91 roy /* 901 1.91 roy * Enter standout mode if appropriate. 902 1.91 roy */ 903 1.91 roy if (on & __STANDOUT && 904 1.91 roy enter_standout_mode != NULL && 905 1.91 roy exit_standout_mode != NULL) 906 1.91 roy { 907 1.91 roy tputs(enter_standout_mode, 0, __cputchar); 908 1.91 roy curscr->wattr |= __STANDOUT; 909 1.91 roy } 910 1.91 roy 911 1.91 roy /* 912 1.91 roy * Enter underscore mode if appropriate. 913 1.91 roy * XXX 914 1.91 roy * Should use uc if us/ue not available. 915 1.91 roy */ 916 1.91 roy if (on & __UNDERSCORE && 917 1.91 roy enter_underline_mode != NULL && 918 1.91 roy exit_underline_mode != NULL) 919 1.91 roy { 920 1.91 roy tputs(enter_underline_mode, 0, __cputchar); 921 1.91 roy curscr->wattr |= __UNDERSCORE; 922 1.91 roy } 923 1.91 roy 924 1.91 roy /* 925 1.91 roy * Set other attributes as appropriate. 926 1.91 roy */ 927 1.91 roy if (exit_attribute_mode != NULL) { 928 1.91 roy if (on & __BLINK && enter_blink_mode != NULL) 929 1.91 roy { 930 1.91 roy tputs(enter_blink_mode, 0, __cputchar); 931 1.91 roy curscr->wattr |= __BLINK; 932 1.91 roy } 933 1.91 roy if (on & __BOLD && enter_bold_mode != NULL) 934 1.91 roy { 935 1.91 roy tputs(enter_bold_mode, 0, __cputchar); 936 1.91 roy curscr->wattr |= __BOLD; 937 1.91 roy } 938 1.91 roy if (on & __DIM && enter_dim_mode != NULL) 939 1.91 roy { 940 1.91 roy tputs(enter_dim_mode, 0, __cputchar); 941 1.91 roy curscr->wattr |= __DIM; 942 1.91 roy } 943 1.91 roy if (on & __BLANK && enter_secure_mode != NULL) 944 1.91 roy { 945 1.91 roy tputs(enter_secure_mode, 0, __cputchar); 946 1.91 roy curscr->wattr |= __BLANK; 947 1.91 roy } 948 1.91 roy if (on & __PROTECT && enter_protected_mode != NULL) 949 1.91 roy { 950 1.91 roy tputs(enter_protected_mode, 0, __cputchar); 951 1.91 roy curscr->wattr |= __PROTECT; 952 1.91 roy } 953 1.91 roy if (on & __REVERSE && enter_reverse_mode != NULL) 954 1.91 roy { 955 1.91 roy tputs(enter_reverse_mode, 0, __cputchar); 956 1.91 roy curscr->wattr |= __REVERSE; 957 1.91 roy } 958 1.91 roy #ifdef HAVE_WCHAR 959 1.91 roy if (on & WA_TOP && enter_top_hl_mode != NULL) 960 1.91 roy { 961 1.91 roy tputs(enter_top_hl_mode, 0, __cputchar); 962 1.91 roy curscr->wattr |= WA_TOP; 963 1.91 roy } 964 1.91 roy if (on & WA_LOW && enter_low_hl_mode != NULL) 965 1.91 roy { 966 1.91 roy tputs(enter_low_hl_mode, 0, __cputchar); 967 1.91 roy curscr->wattr |= WA_LOW; 968 1.91 roy } 969 1.91 roy if (on & WA_LEFT && enter_left_hl_mode != NULL) 970 1.91 roy { 971 1.91 roy tputs(enter_left_hl_mode, 0, __cputchar); 972 1.91 roy curscr->wattr |= WA_LEFT; 973 1.91 roy } 974 1.91 roy if (on & WA_RIGHT && enter_right_hl_mode != NULL) 975 1.91 roy { 976 1.91 roy tputs(enter_right_hl_mode, 0, __cputchar); 977 1.91 roy curscr->wattr |= WA_RIGHT; 978 1.91 roy } 979 1.91 roy if (on & WA_HORIZONTAL && enter_horizontal_hl_mode != NULL) 980 1.91 roy { 981 1.91 roy tputs(enter_horizontal_hl_mode, 0, __cputchar); 982 1.91 roy curscr->wattr |= WA_HORIZONTAL; 983 1.91 roy } 984 1.91 roy if (on & WA_VERTICAL && enter_vertical_hl_mode != NULL) 985 1.91 roy { 986 1.91 roy tputs(enter_vertical_hl_mode, 0, __cputchar); 987 1.91 roy curscr->wattr |= WA_VERTICAL; 988 1.91 roy } 989 1.91 roy #endif /* HAVE_WCHAR */ 990 1.91 roy } 991 1.91 roy 992 1.91 roy /* Enter/exit altcharset mode as appropriate. */ 993 1.91 roy if (on & __ALTCHARSET && enter_alt_charset_mode != NULL && 994 1.91 roy exit_alt_charset_mode != NULL) { 995 1.91 roy tputs(enter_alt_charset_mode, 0, __cputchar); 996 1.91 roy curscr->wattr |= __ALTCHARSET; 997 1.91 roy } 998 1.91 roy } 999 1.91 roy 1000 1.91 roy static void 1001 1.91 roy putattr_out(__LDATA *nsp) 1002 1.91 roy { 1003 1.91 roy 1004 1.91 roy if (underline_char && 1005 1.91 roy ((nsp->attr & __STANDOUT) || (nsp->attr & __UNDERSCORE))) 1006 1.91 roy { 1007 1.91 roy __cputchar('\b'); 1008 1.91 roy tputs(underline_char, 0, __cputchar); 1009 1.91 roy } 1010 1.91 roy } 1011 1.91 roy 1012 1.90 roy static int 1013 1.90 roy putch(__LDATA *nsp, __LDATA *csp, int wy, int wx) 1014 1.90 roy { 1015 1.124 blymn #ifdef HAVE_WCHAR 1016 1.124 blymn int i; 1017 1.124 blymn __LDATA *tcsp; 1018 1.124 blymn #endif /* HAVE_WCHAR */ 1019 1.90 roy 1020 1.91 roy if (csp != NULL) 1021 1.91 roy putattr(nsp); 1022 1.91 roy 1023 1.90 roy if (!_cursesi_screen->curwin && csp) { 1024 1.90 roy csp->attr = nsp->attr; 1025 1.90 roy csp->ch = nsp->ch; 1026 1.124 blymn csp->cflags = nsp->cflags; 1027 1.90 roy #ifdef HAVE_WCHAR 1028 1.90 roy if (_cursesi_copy_nsp(nsp->nsp, csp) == ERR) 1029 1.90 roy return ERR; 1030 1.118 blymn csp->wcols = nsp->wcols; 1031 1.124 blymn 1032 1.124 blymn if (nsp->wcols > 1) { 1033 1.124 blymn tcsp = csp; 1034 1.124 blymn tcsp++; 1035 1.124 blymn for (i = nsp->wcols - 1; i > 0; i--) { 1036 1.124 blymn tcsp->ch = csp->ch; 1037 1.124 blymn tcsp->attr = csp->attr; 1038 1.124 blymn tcsp->wcols = i; 1039 1.124 blymn tcsp->cflags = CA_CONTINUATION; 1040 1.124 blymn tcsp++; 1041 1.124 blymn } 1042 1.124 blymn } 1043 1.90 roy #endif /* HAVE_WCHAR */ 1044 1.90 roy } 1045 1.90 roy 1046 1.90 roy #ifndef HAVE_WCHAR 1047 1.90 roy __cputchar((int)nsp->ch); 1048 1.90 roy #else 1049 1.124 blymn if ((nsp->wcols <= 0) || (nsp->cflags & CA_CONTINUATION)) 1050 1.91 roy goto out; 1051 1.119 blymn 1052 1.119 blymn if (((_cursesi_screen->nca & nsp->attr) == 0) && (__using_color == 1) && 1053 1.119 blymn csp == NULL) 1054 1.119 blymn __set_color(curscr, nsp->attr & __COLOR); 1055 1.90 roy __cputwchar((int)nsp->ch); 1056 1.90 roy __CTRACE(__CTRACE_REFRESH, 1057 1.124 blymn "putch: (%d,%d)putwchar(0x%x)\n", wy, wx, nsp->ch); 1058 1.90 roy 1059 1.90 roy /* Output non-spacing characters for the cell. */ 1060 1.90 roy __cursesi_putnsp(nsp->nsp, wy, wx); 1061 1.91 roy out: 1062 1.90 roy #endif /* HAVE_WCHAR */ 1063 1.90 roy 1064 1.91 roy if (csp != NULL) 1065 1.91 roy putattr_out(nsp); 1066 1.90 roy return OK; 1067 1.90 roy } 1068 1.90 roy 1069 1.90 roy static int 1070 1.90 roy putchbr(__LDATA *nsp, __LDATA *csp, __LDATA *psp, int wy, int wx) 1071 1.90 roy { 1072 1.90 roy int error, cw, pcw; 1073 1.90 roy 1074 1.90 roy /* Can safely print to bottom right corner. */ 1075 1.90 roy if (!auto_right_margin) 1076 1.90 roy return putch(nsp, csp, wy, wx); 1077 1.90 roy 1078 1.90 roy /* Disable auto margins temporarily. */ 1079 1.90 roy if (enter_am_mode && exit_am_mode) { 1080 1.102 roy tputs(exit_am_mode, 0, __cputchar); 1081 1.102 roy error = putch(nsp, csp, wy, wx); 1082 1.90 roy tputs(enter_am_mode, 0, __cputchar); 1083 1.90 roy return error; 1084 1.90 roy } 1085 1.90 roy 1086 1.106 roy /* We need to insert characters. */ 1087 1.90 roy #ifdef HAVE_WCHAR 1088 1.118 blymn cw = nsp->wcols; 1089 1.118 blymn pcw = psp->wcols; 1090 1.106 roy if (cw < 1 || pcw < 1) 1091 1.90 roy return ERR; /* Nothing to insert */ 1092 1.90 roy 1093 1.106 roy /* When inserting a wide character, we need something other than 1094 1.90 roy * insert_character. */ 1095 1.90 roy if (pcw > 1 && 1096 1.90 roy !(parm_ich != NULL || 1097 1.90 roy (enter_insert_mode != NULL && exit_insert_mode != NULL))) 1098 1.90 roy return ERR; 1099 1.90 roy #else 1100 1.90 roy cw = pcw = 1; 1101 1.90 roy #endif /* HAVE_WCHAR */ 1102 1.90 roy 1103 1.90 roy /* Write the corner character at wx - pcw. */ 1104 1.90 roy __mvcur(wy, wx, wy, wx - pcw, 1); 1105 1.90 roy if (putch(nsp, csp, wy, wx) == ERR) 1106 1.90 roy return ERR; 1107 1.90 roy 1108 1.90 roy /* Move cursor back. */ 1109 1.90 roy __mvcur(wy, wx - pcw + cw, wy, wx - cw, 1); 1110 1.90 roy 1111 1.91 roy putattr(psp); 1112 1.91 roy 1113 1.90 roy /* Enter insert mode. */ 1114 1.90 roy if (pcw == 1 && insert_character != NULL) 1115 1.90 roy tputs(insert_character, 0, __cputchar); 1116 1.90 roy else if (parm_ich != NULL) 1117 1.90 roy tputs(tiparm(parm_ich, (long)pcw), 0, __cputchar); 1118 1.90 roy else if (enter_insert_mode != NULL && exit_insert_mode != NULL) 1119 1.90 roy tputs(enter_insert_mode, 0, __cputchar); 1120 1.90 roy else 1121 1.90 roy return ERR; 1122 1.90 roy 1123 1.90 roy /* Insert the old character back. */ 1124 1.90 roy error = putch(psp, NULL, wy, wx - pcw); 1125 1.90 roy 1126 1.90 roy /* Exit insert mode. */ 1127 1.90 roy if (insert_character != NULL || parm_ich != NULL) 1128 1.90 roy ; 1129 1.90 roy else if (enter_insert_mode != NULL && exit_insert_mode != NULL) 1130 1.90 roy tputs(exit_insert_mode, 0, __cputchar); 1131 1.90 roy 1132 1.91 roy putattr_out(psp); 1133 1.91 roy 1134 1.90 roy return error; 1135 1.90 roy } 1136 1.90 roy 1137 1.1 cgd /* 1138 1.4 mycroft * makech -- 1139 1.4 mycroft * Make a change on the screen. 1140 1.1 cgd */ 1141 1.4 mycroft static int 1142 1.65 blymn makech(int wy) 1143 1.1 cgd { 1144 1.23 jdc WINDOW *win; 1145 1.124 blymn static __LDATA blank; 1146 1.124 blymn __LDATA *nsp, *csp, *cp, *cep, *fsp; 1147 1.78 blymn __LINE *wlp; 1148 1.124 blymn int nlsp; /* offset to first space at eol. */ 1149 1.124 blymn size_t mlsp; 1150 1.118 blymn int lch, wx, owx, chw; 1151 1.72 roy const char *ce; 1152 1.23 jdc attr_t lspc; /* Last space colour */ 1153 1.119 blymn attr_t battr; /* background attribute bits */ 1154 1.119 blymn attr_t attr_mask; /* attributes mask */ 1155 1.5 cgd 1156 1.8 mikel #ifdef __GNUC__ 1157 1.23 jdc nlsp = lspc = 0; /* XXX gcc -Wuninitialized */ 1158 1.8 mikel #endif 1159 1.43 blymn if (_cursesi_screen->curwin) 1160 1.23 jdc win = curscr; 1161 1.23 jdc else 1162 1.23 jdc win = __virtscr; 1163 1.119 blymn 1164 1.119 blymn blank.ch = win->bch; 1165 1.119 blymn blank.attr = win->battr; 1166 1.124 blymn blank.cflags = CA_BACKGROUND; 1167 1.65 blymn #ifdef HAVE_WCHAR 1168 1.65 blymn if (_cursesi_copy_nsp(win->bnsp, &blank) == ERR) 1169 1.65 blymn return ERR; 1170 1.118 blymn blank.wcols = win->wcols; 1171 1.119 blymn attr_mask = WA_ATTRIBUTES; 1172 1.119 blymn #else 1173 1.119 blymn attr_mask = A_ATTRIBUTES; 1174 1.65 blymn #endif /* HAVE_WCHAR */ 1175 1.119 blymn battr = win->battr & attr_mask; 1176 1.119 blymn 1177 1.65 blymn #ifdef DEBUG 1178 1.65 blymn #if HAVE_WCHAR 1179 1.65 blymn { 1180 1.65 blymn int x; 1181 1.65 blymn __LDATA *lp, *vlp; 1182 1.65 blymn 1183 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1184 1.65 blymn "[makech-before]wy=%d,curscr(%p)-__virtscr(%p)\n", 1185 1.65 blymn wy, curscr, __virtscr); 1186 1.65 blymn for (x = 0; x < curscr->maxx; x++) { 1187 1.71 roy lp = &curscr->alines[wy]->line[x]; 1188 1.71 roy vlp = &__virtscr->alines[wy]->line[x]; 1189 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1190 1.118 blymn "[%d,%d](%x,%x,%d,%x,%x,%d,%p)-" 1191 1.118 blymn "(%x,%x,%d,%x,%x,%d,%p)\n", 1192 1.118 blymn wy, x, lp->ch, lp->attr, lp->wcols, 1193 1.118 blymn win->bch, win->battr, win->wcols, lp->nsp, 1194 1.118 blymn vlp->ch, vlp->attr, vlp->wcols, 1195 1.118 blymn win->bch, win->battr, win->wcols, vlp->nsp); 1196 1.65 blymn } 1197 1.65 blymn } 1198 1.65 blymn #endif /* HAVE_WCHAR */ 1199 1.65 blymn #endif /* DEBUG */ 1200 1.119 blymn 1201 1.5 cgd /* Is the cursor still on the end of the last line? */ 1202 1.71 roy if (wy > 0 && curscr->alines[wy - 1]->flags & __ISPASTEOL) { 1203 1.84 roy domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx, 1204 1.43 blymn _cursesi_screen->ly + 1, 0); 1205 1.43 blymn _cursesi_screen->ly++; 1206 1.43 blymn _cursesi_screen->lx = 0; 1207 1.5 cgd } 1208 1.78 blymn wlp = win->alines[wy]; 1209 1.71 roy wx = *win->alines[wy]->firstchp; 1210 1.5 cgd if (wx < 0) 1211 1.5 cgd wx = 0; 1212 1.11 mrg else 1213 1.11 mrg if (wx >= win->maxx) 1214 1.11 mrg return (OK); 1215 1.71 roy lch = *win->alines[wy]->lastchp; 1216 1.1 cgd if (lch < 0) 1217 1.83 roy return OK; 1218 1.11 mrg else 1219 1.11 mrg if (lch >= (int) win->maxx) 1220 1.11 mrg lch = win->maxx - 1; 1221 1.1 cgd 1222 1.65 blymn if (_cursesi_screen->curwin) { 1223 1.5 cgd csp = ␣ 1224 1.65 blymn __CTRACE(__CTRACE_REFRESH, "makech: csp is blank\n"); 1225 1.65 blymn } else { 1226 1.71 roy csp = &curscr->alines[wy]->line[wx]; 1227 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1228 1.65 blymn "makech: csp is on curscr:(%d,%d)\n", wy, wx); 1229 1.65 blymn } 1230 1.1 cgd 1231 1.124 blymn 1232 1.124 blymn while (win->alines[wy]->line[wx].cflags & CA_CONTINUATION) { 1233 1.124 blymn wx--; 1234 1.124 blymn if (wx <= 0) { 1235 1.124 blymn wx = 0; 1236 1.124 blymn break; 1237 1.124 blymn } 1238 1.124 blymn } 1239 1.124 blymn 1240 1.90 roy nsp = fsp = &win->alines[wy]->line[wx]; 1241 1.119 blymn 1242 1.65 blymn #ifdef DEBUG 1243 1.83 roy if (_cursesi_screen->curwin) 1244 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1245 1.65 blymn "makech: nsp is at curscr:(%d,%d)\n", wy, wx); 1246 1.65 blymn else 1247 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1248 1.65 blymn "makech: nsp is at __virtscr:(%d,%d)\n", wy, wx); 1249 1.65 blymn #endif /* DEBUG */ 1250 1.119 blymn 1251 1.119 blymn /* 1252 1.119 blymn * Work out if we can use a clear to end of line. If we are 1253 1.119 blymn * using color then we can only erase the line if the terminal 1254 1.119 blymn * can erase to the background color. 1255 1.119 blymn */ 1256 1.119 blymn if (clr_eol && !_cursesi_screen->curwin && (!(__using_color) 1257 1.119 blymn || (__using_color && back_color_erase))) { 1258 1.124 blymn nlsp = win->maxx - 1; 1259 1.71 roy cp = &win->alines[wy]->line[win->maxx - 1]; 1260 1.119 blymn #ifdef HAVE_WCHAR 1261 1.124 blymn while ((_cursesi_celleq(cp, &blank) == 1) && 1262 1.65 blymn #else 1263 1.124 blymn while (cp->ch == blank.ch && 1264 1.119 blymn #endif /* HAVE_WCHAR */ 1265 1.119 blymn ((cp->attr & attr_mask) == battr)) { 1266 1.124 blymn #ifdef HAVE_WCHAR 1267 1.124 blymn nlsp -= cp->wcols; 1268 1.124 blymn cp -= cp->wcols; 1269 1.124 blymn #else 1270 1.124 blymn nlsp--; 1271 1.124 blymn cp--; 1272 1.124 blymn #endif /* HAVE_WCHAR */ 1273 1.124 blymn 1274 1.124 blymn if (nlsp <= 0) 1275 1.1 cgd break; 1276 1.119 blymn } 1277 1.119 blymn 1278 1.119 blymn 1279 1.124 blymn if (nlsp < 0) 1280 1.42 blymn nlsp = 0; 1281 1.1 cgd } 1282 1.119 blymn 1283 1.119 blymn ce = clr_eol; 1284 1.1 cgd 1285 1.1 cgd while (wx <= lch) { 1286 1.124 blymn __CTRACE(__CTRACE_REFRESH, "makech: wx=%d,lch=%d, nlsp=%d\n", wx, lch, nlsp); 1287 1.119 blymn #ifdef HAVE_WCHAR 1288 1.123 blymn __CTRACE(__CTRACE_REFRESH, "makech: farnarkle: flags 0x%x, cflags 0x%x, color_init %d, celleq %d\n", 1289 1.123 blymn wlp->flags, nsp->cflags, __do_color_init, _cursesi_celleq(nsp, csp)); 1290 1.118 blymn __CTRACE(__CTRACE_REFRESH, "makech: nsp=(%x,%x,%d,%x,%x,%d,%p)\n", 1291 1.118 blymn nsp->ch, nsp->attr, nsp->wcols, win->bch, win->battr, 1292 1.118 blymn win->wcols, nsp->nsp); 1293 1.118 blymn __CTRACE(__CTRACE_REFRESH, "makech: csp=(%x,%x,%d,%x,%x,%d,%p)\n", 1294 1.118 blymn csp->ch, csp->attr, csp->wcols, win->bch, win->battr, 1295 1.118 blymn win->wcols, csp->nsp); 1296 1.98 uwe #endif 1297 1.78 blymn if (!(wlp->flags & __ISFORCED) && 1298 1.98 uwe #ifdef HAVE_WCHAR 1299 1.123 blymn ((nsp->cflags & CA_CONTINUATION) != CA_CONTINUATION) && 1300 1.98 uwe #endif 1301 1.122 blymn _cursesi_celleq(nsp, csp)) 1302 1.83 roy { 1303 1.65 blymn if (wx <= lch) { 1304 1.122 blymn while (wx <= lch && _cursesi_celleq(nsp, csp)) { 1305 1.118 blymn #ifdef HAVE_WCHAR 1306 1.118 blymn wx += nsp->wcols; 1307 1.124 blymn if (!_cursesi_screen->curwin) 1308 1.124 blymn csp += nsp->wcols; 1309 1.124 blymn nsp += nsp->wcols; 1310 1.118 blymn #else 1311 1.118 blymn wx++; 1312 1.65 blymn nsp++; 1313 1.65 blymn if (!_cursesi_screen->curwin) 1314 1.65 blymn ++csp; 1315 1.124 blymn #endif 1316 1.65 blymn } 1317 1.65 blymn continue; 1318 1.65 blymn } 1319 1.65 blymn break; 1320 1.65 blymn } 1321 1.98 uwe 1322 1.84 roy domvcur(win, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx); 1323 1.5 cgd 1324 1.64 jdc __CTRACE(__CTRACE_REFRESH, "makech: 1: wx = %d, ly= %d, " 1325 1.119 blymn "lx = %d, newy = %d, newx = %d, lch = %d\n", 1326 1.119 blymn wx, _cursesi_screen->ly, _cursesi_screen->lx, wy, wx, lch); 1327 1.43 blymn _cursesi_screen->ly = wy; 1328 1.43 blymn _cursesi_screen->lx = wx; 1329 1.118 blymn owx = wx; 1330 1.92 uwe while (wx <= lch && 1331 1.122 blymn ((wlp->flags & __ISFORCED) || !_cursesi_celleq(nsp, csp))) 1332 1.83 roy { 1333 1.119 blymn if ((ce != NULL) && (wx >= nlsp) && 1334 1.124 blymn (nsp->ch == blank.ch) && 1335 1.124 blymn (__do_color_init == 1 || nsp->attr == blank.attr)) 1336 1.83 roy { 1337 1.4 mycroft /* Check for clear to end-of-line. */ 1338 1.124 blymn cep = &win->alines[wy]->line[win->maxx - 1]; 1339 1.119 blymn while (cep->ch == blank.ch && cep->attr == battr) 1340 1.5 cgd if (cep-- <= csp) 1341 1.4 mycroft break; 1342 1.124 blymn 1343 1.124 blymn mlsp = &win->alines[wy]->line[win->maxx - 1] 1344 1.124 blymn - win->alines[wy]->line 1345 1.124 blymn - win->begx * __LDATASIZE; 1346 1.124 blymn 1347 1.64 jdc __CTRACE(__CTRACE_REFRESH, 1348 1.124 blymn "makech: nlsp = %d, max = %zu, strlen(ce) = %zu\n", 1349 1.124 blymn nlsp, mlsp, strlen(ce)); 1350 1.78 blymn __CTRACE(__CTRACE_REFRESH, 1351 1.78 blymn "makech: line = %p, cep = %p, begx = %u\n", 1352 1.124 blymn win->alines[wy]->line, cep, win->begx); 1353 1.119 blymn 1354 1.119 blymn /* 1355 1.119 blymn * work out how to clear the line. If: 1356 1.119 blymn * - clear len is greater than clear_to_eol len 1357 1.119 blymn * - background char == ' ' 1358 1.119 blymn * - we are not at EOL 1359 1.119 blymn * - using color and term can erase to 1360 1.119 blymn * background color 1361 1.119 blymn * - if we are at the bottom of the window 1362 1.119 blymn * (to prevent a scroll) 1363 1.119 blymn * then emit the ce string. 1364 1.119 blymn */ 1365 1.124 blymn if (((wy == win->maxy - 1) || 1366 1.124 blymn ((mlsp - wx) > strlen(ce))) && 1367 1.124 blymn ((__using_color && back_color_erase) || 1368 1.124 blymn (! __using_color))) { 1369 1.124 blymn if (wlp->line[wx].attr & win->screen->nca) { 1370 1.119 blymn __unsetattr(0); 1371 1.119 blymn } else if (__using_color && 1372 1.119 blymn ((__do_color_init == 1) || 1373 1.47 jdc ((lspc & __COLOR) != 1374 1.119 blymn (curscr->wattr & __COLOR)))) { 1375 1.47 jdc __set_color(curscr, lspc & 1376 1.47 jdc __COLOR); 1377 1.119 blymn } 1378 1.88 christos tputs(ce, 0, __cputchar); 1379 1.43 blymn _cursesi_screen->lx = wx + win->begx; 1380 1.124 blymn csp = &curscr->alines[wy]->line[wx + win->begx]; 1381 1.124 blymn wx = wx + win->begx; 1382 1.124 blymn while (wx++ <= (curscr->maxx - 1)) { 1383 1.119 blymn csp->attr = blank.attr; 1384 1.119 blymn csp->ch = blank.ch; 1385 1.124 blymn csp->cflags = CA_BACKGROUND; 1386 1.119 blymn #ifdef HAVE_WCHAR 1387 1.119 blymn if (_cursesi_copy_nsp(blank.nsp, csp) == ERR) 1388 1.119 blymn return ERR; 1389 1.120 blymn csp->wcols = blank.wcols; 1390 1.124 blymn csp += blank.wcols; 1391 1.124 blymn #else 1392 1.124 blymn csp++; 1393 1.65 blymn #endif /* HAVE_WCHAR */ 1394 1.113 mrg assert(csp != &blank); 1395 1.5 cgd } 1396 1.83 roy return OK; 1397 1.1 cgd } 1398 1.4 mycroft } 1399 1.4 mycroft 1400 1.90 roy #ifdef HAVE_WCHAR 1401 1.118 blymn chw = nsp->wcols; 1402 1.106 roy if (chw < 0) 1403 1.107 roy chw = 0; /* match putch() */ 1404 1.90 roy #else 1405 1.90 roy chw = 1; 1406 1.90 roy #endif /* HAVE_WCHAR */ 1407 1.118 blymn owx = wx; 1408 1.124 blymn if (wx + chw >= (win->maxx) && 1409 1.91 roy wy == win->maxy - 1 && !_cursesi_screen->curwin) 1410 1.91 roy { 1411 1.89 roy if (win->flags & __ENDLINE) 1412 1.89 roy __unsetattr(1); 1413 1.89 roy if (!(win->flags & __SCROLLWIN)) { 1414 1.90 roy int e; 1415 1.90 roy 1416 1.90 roy if (win->flags & __SCROLLOK) 1417 1.90 roy e = putch(nsp, csp, wy, wx); 1418 1.124 blymn else { 1419 1.90 roy e = putchbr(nsp, csp, 1420 1.90 roy nsp == fsp ? NULL : nsp - 1, 1421 1.90 roy wy, wx); 1422 1.124 blymn } 1423 1.90 roy if (e == ERR) 1424 1.90 roy return ERR; 1425 1.7 cgd } 1426 1.90 roy if (wx + chw < curscr->maxx) { 1427 1.89 roy domvcur(win, 1428 1.89 roy _cursesi_screen->ly, wx, 1429 1.89 roy (int)(win->maxy - 1), 1430 1.89 roy (int)(win->maxx - 1)); 1431 1.89 roy } 1432 1.89 roy _cursesi_screen->ly = win->maxy - 1; 1433 1.89 roy _cursesi_screen->lx = win->maxx - 1; 1434 1.89 roy return OK; 1435 1.65 blymn } 1436 1.90 roy if (wx + chw < win->maxx || wy < win->maxy - 1 || 1437 1.83 roy !(win->flags & __SCROLLWIN)) 1438 1.83 roy { 1439 1.124 blymn if (putch(nsp, csp, wy, wx) == ERR) 1440 1.90 roy return ERR; 1441 1.91 roy } else { 1442 1.91 roy putattr(nsp); 1443 1.91 roy putattr_out(nsp); 1444 1.1 cgd } 1445 1.90 roy wx += chw; 1446 1.118 blymn nsp += chw; 1447 1.124 blymn if (!_cursesi_screen->curwin) 1448 1.124 blymn csp += chw; 1449 1.124 blymn 1450 1.64 jdc __CTRACE(__CTRACE_REFRESH, 1451 1.64 jdc "makech: 2: wx = %d, lx = %d\n", 1452 1.64 jdc wx, _cursesi_screen->lx); 1453 1.5 cgd } 1454 1.43 blymn if (_cursesi_screen->lx == wx) /* If no change. */ 1455 1.4 mycroft break; 1456 1.118 blymn 1457 1.118 blymn /* 1458 1.118 blymn * We need to work out if the cursor has been put in the 1459 1.118 blymn * middle of a wide character so check if curx is between 1460 1.118 blymn * where we were and where we are and we are on the right 1461 1.118 blymn * line. If so, move the cursor now. 1462 1.118 blymn */ 1463 1.118 blymn if ((wy == win->cury) && (wx > win->curx) && 1464 1.118 blymn (owx < win->curx)) { 1465 1.118 blymn _cursesi_screen->lx = win->curx; 1466 1.118 blymn domvcur(win, _cursesi_screen->ly, wx, 1467 1.118 blymn _cursesi_screen->ly, _cursesi_screen->lx); 1468 1.118 blymn } else 1469 1.118 blymn _cursesi_screen->lx = wx; 1470 1.118 blymn 1471 1.72 roy if (_cursesi_screen->lx >= COLS && auto_right_margin) 1472 1.43 blymn _cursesi_screen->lx = COLS - 1; 1473 1.11 mrg else 1474 1.11 mrg if (wx >= win->maxx) { 1475 1.84 roy domvcur(win, 1476 1.84 roy _cursesi_screen->ly, 1477 1.43 blymn _cursesi_screen->lx, 1478 1.43 blymn _cursesi_screen->ly, 1479 1.84 roy (int)(win->maxx - 1)); 1480 1.43 blymn _cursesi_screen->lx = win->maxx - 1; 1481 1.11 mrg } 1482 1.64 jdc __CTRACE(__CTRACE_REFRESH, "makech: 3: wx = %d, lx = %d\n", 1483 1.64 jdc wx, _cursesi_screen->lx); 1484 1.1 cgd } 1485 1.65 blymn #ifdef DEBUG 1486 1.65 blymn #if HAVE_WCHAR 1487 1.65 blymn { 1488 1.65 blymn int x; 1489 1.65 blymn __LDATA *lp, *vlp; 1490 1.65 blymn 1491 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1492 1.65 blymn "makech-after: curscr(%p)-__virtscr(%p)\n", 1493 1.65 blymn curscr, __virtscr ); 1494 1.65 blymn for (x = 0; x < curscr->maxx; x++) { 1495 1.71 roy lp = &curscr->alines[wy]->line[x]; 1496 1.71 roy vlp = &__virtscr->alines[wy]->line[x]; 1497 1.65 blymn __CTRACE(__CTRACE_REFRESH, 1498 1.118 blymn "[%d,%d](%x,%x,%d,%x,%x,%d,%p)-" 1499 1.118 blymn "(%x,%x,%d,%x,%x,%d,%p)\n", 1500 1.118 blymn wy, x, lp->ch, lp->attr, lp->wcols, 1501 1.118 blymn win->bch, win->battr, win->wcols, lp->nsp, 1502 1.118 blymn vlp->ch, vlp->attr, vlp->wcols, 1503 1.118 blymn win->bch, win->battr, win->wcols, vlp->nsp); 1504 1.65 blymn } 1505 1.65 blymn } 1506 1.65 blymn #endif /* HAVE_WCHAR */ 1507 1.65 blymn #endif /* DEBUG */ 1508 1.7 cgd 1509 1.83 roy return OK; 1510 1.1 cgd } 1511 1.1 cgd 1512 1.1 cgd /* 1513 1.4 mycroft * domvcur -- 1514 1.19 jdc * Do a mvcur, leaving attributes if necessary. 1515 1.1 cgd */ 1516 1.4 mycroft static void 1517 1.110 blymn domvcur(WINDOW *win, int oy, int ox, int ny, int nx) 1518 1.4 mycroft { 1519 1.83 roy 1520 1.112 rin __CTRACE(__CTRACE_REFRESH, "domvcur: (%d,%d)=>(%d,%d) win %p\n", 1521 1.111 blymn oy, ox, ny, nx, win ); 1522 1.84 roy 1523 1.23 jdc __unsetattr(1); 1524 1.84 roy 1525 1.84 roy /* Don't move the cursor unless we need to. */ 1526 1.84 roy if (oy == ny && ox == nx) { 1527 1.84 roy /* Check EOL. */ 1528 1.84 roy if (!(win->alines[oy]->flags & __ISPASTEOL)) 1529 1.84 roy return; 1530 1.84 roy } 1531 1.84 roy 1532 1.84 roy /* Clear EOL flags. */ 1533 1.84 roy win->alines[oy]->flags &= ~__ISPASTEOL; 1534 1.84 roy win->alines[ny]->flags &= ~__ISPASTEOL; 1535 1.84 roy 1536 1.5 cgd __mvcur(oy, ox, ny, nx, 1); 1537 1.5 cgd } 1538 1.5 cgd 1539 1.5 cgd /* 1540 1.5 cgd * Quickch() attempts to detect a pattern in the change of the window 1541 1.7 cgd * in order to optimize the change, e.g., scroll n lines as opposed to 1542 1.5 cgd * repainting the screen line by line. 1543 1.5 cgd */ 1544 1.5 cgd 1545 1.46 christos static __LDATA buf[128]; 1546 1.82 roy static unsigned int last_hash; 1547 1.46 christos static size_t last_hash_len; 1548 1.46 christos #define BLANKSIZE (sizeof(buf) / sizeof(buf[0])) 1549 1.46 christos 1550 1.5 cgd static void 1551 1.23 jdc quickch(void) 1552 1.5 cgd { 1553 1.23 jdc #define THRESH (int) __virtscr->maxy / 4 1554 1.5 cgd 1555 1.10 perry __LINE *clp, *tmp1, *tmp2; 1556 1.11 mrg int bsize, curs, curw, starts, startw, i, j; 1557 1.11 mrg int n, target, cur_period, bot, top, sc_region; 1558 1.119 blymn unsigned int blank_hash, found; 1559 1.22 jdc attr_t bcolor; 1560 1.5 cgd 1561 1.8 mikel #ifdef __GNUC__ 1562 1.11 mrg curs = curw = starts = startw = 0; /* XXX gcc -Wuninitialized */ 1563 1.8 mikel #endif 1564 1.7 cgd /* 1565 1.5 cgd * Find how many lines from the top of the screen are unchanged. 1566 1.5 cgd */ 1567 1.83 roy for (top = 0; top < __virtscr->maxy; top++) { 1568 1.71 roy if (__virtscr->alines[top]->flags & __ISDIRTY && 1569 1.71 roy (__virtscr->alines[top]->hash != curscr->alines[top]->hash || 1570 1.101 uwe !lineeq(__virtscr->alines[top]->line, 1571 1.101 uwe curscr->alines[top]->line, 1572 1.119 blymn (size_t) __virtscr->maxx))) { 1573 1.5 cgd break; 1574 1.119 blymn } else 1575 1.71 roy __virtscr->alines[top]->flags &= ~__ISDIRTY; 1576 1.83 roy } 1577 1.11 mrg /* 1578 1.11 mrg * Find how many lines from bottom of screen are unchanged. 1579 1.11 mrg */ 1580 1.83 roy for (bot = __virtscr->maxy - 1; bot >= 0; bot--) { 1581 1.71 roy if (__virtscr->alines[bot]->flags & __ISDIRTY && 1582 1.71 roy (__virtscr->alines[bot]->hash != curscr->alines[bot]->hash || 1583 1.101 uwe !lineeq(__virtscr->alines[bot]->line, 1584 1.101 uwe curscr->alines[bot]->line, 1585 1.119 blymn (size_t) __virtscr->maxx))) { 1586 1.5 cgd break; 1587 1.119 blymn } else 1588 1.71 roy __virtscr->alines[bot]->flags &= ~__ISDIRTY; 1589 1.83 roy } 1590 1.23 jdc 1591 1.23 jdc /* 1592 1.23 jdc * Work round an xterm bug where inserting lines causes all the 1593 1.23 jdc * inserted lines to be covered with the background colour we 1594 1.23 jdc * set on the first line (even if we unset it for subsequent 1595 1.23 jdc * lines). 1596 1.23 jdc */ 1597 1.71 roy bcolor = __virtscr->alines[min(top, 1598 1.23 jdc __virtscr->maxy - 1)]->line[0].attr & __COLOR; 1599 1.23 jdc for (i = top + 1, j = 0; i < bot; i++) { 1600 1.71 roy if ((__virtscr->alines[i]->line[0].attr & __COLOR) != bcolor) { 1601 1.71 roy bcolor = __virtscr->alines[i]->line[__virtscr->maxx]. 1602 1.23 jdc attr & __COLOR; 1603 1.23 jdc j = i - top; 1604 1.23 jdc } else 1605 1.23 jdc break; 1606 1.23 jdc } 1607 1.23 jdc top += j; 1608 1.5 cgd 1609 1.5 cgd #ifdef NO_JERKINESS 1610 1.5 cgd /* 1611 1.5 cgd * If we have a bottom unchanged region return. Scrolling the 1612 1.5 cgd * bottom region up and then back down causes a screen jitter. 1613 1.5 cgd * This will increase the number of characters sent to the screen 1614 1.5 cgd * but it looks better. 1615 1.5 cgd */ 1616 1.23 jdc if (bot < __virtscr->maxy - 1) 1617 1.5 cgd return; 1618 1.11 mrg #endif /* NO_JERKINESS */ 1619 1.5 cgd 1620 1.5 cgd /* 1621 1.5 cgd * Search for the largest block of text not changed. 1622 1.5 cgd * Invariants of the loop: 1623 1.23 jdc * - Startw is the index of the beginning of the examined block in 1624 1.23 jdc * __virtscr. 1625 1.11 mrg * - Starts is the index of the beginning of the examined block in 1626 1.23 jdc * curscr. 1627 1.7 cgd * - Curw is the index of one past the end of the exmined block in 1628 1.23 jdc * __virtscr. 1629 1.23 jdc * - Curs is the index of one past the end of the exmined block in 1630 1.5 cgd * curscr. 1631 1.5 cgd * - bsize is the current size of the examined block. 1632 1.11 mrg */ 1633 1.23 jdc 1634 1.119 blymn found = 0; 1635 1.5 cgd for (bsize = bot - top; bsize >= THRESH; bsize--) { 1636 1.5 cgd for (startw = top; startw <= bot - bsize; startw++) 1637 1.83 roy for (starts = top; starts <= bot - bsize; starts++) { 1638 1.119 blymn /* for (curw = startw, curs = starts; 1639 1.11 mrg curs < starts + bsize; curw++, curs++) 1640 1.71 roy if (__virtscr->alines[curw]->hash != 1641 1.71 roy curscr->alines[curs]->hash) 1642 1.32 mycroft break; 1643 1.32 mycroft if (curs != starts + bsize) 1644 1.119 blymn continue;*/ 1645 1.32 mycroft for (curw = startw, curs = starts; 1646 1.65 blymn curs < starts + bsize; curw++, curs++) 1647 1.96 uwe if (!lineeq(__virtscr->alines[curw]->line, 1648 1.101 uwe curscr->alines[curs]->line, 1649 1.119 blymn (size_t) __virtscr->maxx)) { 1650 1.119 blymn found = 1; 1651 1.5 cgd break; 1652 1.119 blymn } 1653 1.119 blymn if ((curs == starts + bsize) && (found == 1)) { 1654 1.5 cgd goto done; 1655 1.119 blymn } 1656 1.5 cgd } 1657 1.5 cgd } 1658 1.11 mrg done: 1659 1.22 jdc 1660 1.119 blymn __CTRACE(__CTRACE_REFRESH, "quickch:bsize=%d, THRESH=%d, starts=%d, " 1661 1.119 blymn "startw=%d, curw=%d, curs=%d, top=%d, bot=%d\n", 1662 1.119 blymn bsize, THRESH, starts, startw, curw, curs, top, bot); 1663 1.119 blymn 1664 1.5 cgd /* Did not find anything */ 1665 1.7 cgd if (bsize < THRESH) 1666 1.5 cgd return; 1667 1.5 cgd 1668 1.7 cgd /* 1669 1.7 cgd * Make sure that there is no overlap between the bottom and top 1670 1.5 cgd * regions and the middle scrolled block. 1671 1.5 cgd */ 1672 1.5 cgd if (bot < curs) 1673 1.5 cgd bot = curs - 1; 1674 1.5 cgd if (top > starts) 1675 1.5 cgd top = starts; 1676 1.5 cgd 1677 1.5 cgd n = startw - starts; 1678 1.5 cgd 1679 1.5 cgd #ifdef DEBUG 1680 1.64 jdc __CTRACE(__CTRACE_REFRESH, "#####################################\n"); 1681 1.119 blymn __CTRACE(__CTRACE_REFRESH, "quickch: n = %d\n", n); 1682 1.11 mrg for (i = 0; i < curscr->maxy; i++) { 1683 1.64 jdc __CTRACE(__CTRACE_REFRESH, "C: %d:", i); 1684 1.71 roy __CTRACE(__CTRACE_REFRESH, " 0x%x \n", curscr->alines[i]->hash); 1685 1.11 mrg for (j = 0; j < curscr->maxx; j++) 1686 1.64 jdc __CTRACE(__CTRACE_REFRESH, "%c", 1687 1.71 roy curscr->alines[i]->line[j].ch); 1688 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 1689 1.64 jdc __CTRACE(__CTRACE_REFRESH, " attr:"); 1690 1.11 mrg for (j = 0; j < curscr->maxx; j++) 1691 1.64 jdc __CTRACE(__CTRACE_REFRESH, " %x", 1692 1.71 roy curscr->alines[i]->line[j].attr); 1693 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 1694 1.64 jdc __CTRACE(__CTRACE_REFRESH, "W: %d:", i); 1695 1.64 jdc __CTRACE(__CTRACE_REFRESH, " 0x%x \n", 1696 1.71 roy __virtscr->alines[i]->hash); 1697 1.64 jdc __CTRACE(__CTRACE_REFRESH, " 0x%x ", 1698 1.71 roy __virtscr->alines[i]->flags); 1699 1.23 jdc for (j = 0; j < __virtscr->maxx; j++) 1700 1.64 jdc __CTRACE(__CTRACE_REFRESH, "%c", 1701 1.71 roy __virtscr->alines[i]->line[j].ch); 1702 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 1703 1.64 jdc __CTRACE(__CTRACE_REFRESH, " attr:"); 1704 1.23 jdc for (j = 0; j < __virtscr->maxx; j++) 1705 1.64 jdc __CTRACE(__CTRACE_REFRESH, " %x", 1706 1.71 roy __virtscr->alines[i]->line[j].attr); 1707 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 1708 1.11 mrg } 1709 1.7 cgd #endif 1710 1.7 cgd 1711 1.65 blymn #ifndef HAVE_WCHAR 1712 1.119 blymn if (buf[0].ch != curscr->bch) { 1713 1.46 christos for (i = 0; i < BLANKSIZE; i++) { 1714 1.119 blymn buf[i].ch = curscr->bch; 1715 1.46 christos buf[i].attr = 0; 1716 1.124 blymn buf[i].cflags = CA_BACKGROUND; 1717 1.46 christos } 1718 1.5 cgd } 1719 1.65 blymn #else 1720 1.119 blymn if (buf[0].ch != curscr->bch) { 1721 1.118 blymn for (i = 0; i < BLANKSIZE; i++) { /* XXXX: BLANKSIZE may not be valid if wcols > 1 */ 1722 1.119 blymn buf[i].ch = curscr->bch; 1723 1.65 blymn if (_cursesi_copy_nsp(curscr->bnsp, &buf[i]) == ERR) 1724 1.65 blymn return; 1725 1.65 blymn buf[i].attr = 0; 1726 1.124 blymn buf[i].cflags = CA_BACKGROUND; 1727 1.118 blymn buf[i].wcols = curscr->wcols; 1728 1.65 blymn } 1729 1.65 blymn } 1730 1.65 blymn #endif /* HAVE_WCHAR */ 1731 1.46 christos 1732 1.46 christos if (__virtscr->maxx != last_hash_len) { 1733 1.46 christos blank_hash = 0; 1734 1.46 christos for (i = __virtscr->maxx; i > BLANKSIZE; i -= BLANKSIZE) { 1735 1.61 dsl blank_hash = __hash_more(buf, sizeof(buf), blank_hash); 1736 1.46 christos } 1737 1.46 christos blank_hash = __hash_more((char *)(void *)buf, 1738 1.46 christos i * sizeof(buf[0]), blank_hash); 1739 1.46 christos /* cache result in static data - screen width doesn't change often */ 1740 1.46 christos last_hash_len = __virtscr->maxx; 1741 1.46 christos last_hash = blank_hash; 1742 1.46 christos } else 1743 1.46 christos blank_hash = last_hash; 1744 1.5 cgd 1745 1.5 cgd /* 1746 1.5 cgd * Perform the rotation to maintain the consistency of curscr. 1747 1.5 cgd * This is hairy since we are doing an *in place* rotation. 1748 1.5 cgd * Invariants of the loop: 1749 1.5 cgd * - I is the index of the current line. 1750 1.5 cgd * - Target is the index of the target of line i. 1751 1.5 cgd * - Tmp1 points to current line (i). 1752 1.5 cgd * - Tmp2 and points to target line (target); 1753 1.7 cgd * - Cur_period is the index of the end of the current period. 1754 1.5 cgd * (see below). 1755 1.5 cgd * 1756 1.5 cgd * There are 2 major issues here that make this rotation non-trivial: 1757 1.5 cgd * 1. Scrolling in a scrolling region bounded by the top 1758 1.5 cgd * and bottom regions determined (whose size is sc_region). 1759 1.7 cgd * 2. As a result of the use of the mod function, there may be a 1760 1.5 cgd * period introduced, i.e., 2 maps to 4, 4 to 6, n-2 to 0, and 1761 1.5 cgd * 0 to 2, which then causes all odd lines not to be rotated. 1762 1.7 cgd * To remedy this, an index of the end ( = beginning) of the 1763 1.7 cgd * current 'period' is kept, cur_period, and when it is reached, 1764 1.7 cgd * the next period is started from cur_period + 1 which is 1765 1.5 cgd * guaranteed not to have been reached since that would mean that 1766 1.5 cgd * all records would have been reached. (think about it...). 1767 1.7 cgd * 1768 1.5 cgd * Lines in the rotation can have 3 attributes which are marked on the 1769 1.5 cgd * line so that curscr is consistent with the visual screen. 1770 1.5 cgd * 1. Not dirty -- lines inside the scrolled block, top region or 1771 1.5 cgd * bottom region. 1772 1.7 cgd * 2. Blank lines -- lines in the differential of the scrolling 1773 1.7 cgd * region adjacent to top and bot regions 1774 1.5 cgd * depending on scrolling direction. 1775 1.5 cgd * 3. Dirty line -- all other lines are marked dirty. 1776 1.5 cgd */ 1777 1.5 cgd sc_region = bot - top + 1; 1778 1.5 cgd i = top; 1779 1.71 roy tmp1 = curscr->alines[top]; 1780 1.5 cgd cur_period = top; 1781 1.5 cgd for (j = top; j <= bot; j++) { 1782 1.5 cgd target = (i - top + n + sc_region) % sc_region + top; 1783 1.71 roy tmp2 = curscr->alines[target]; 1784 1.71 roy curscr->alines[target] = tmp1; 1785 1.5 cgd /* Mark block as clean and blank out scrolled lines. */ 1786 1.71 roy clp = curscr->alines[target]; 1787 1.64 jdc __CTRACE(__CTRACE_REFRESH, 1788 1.64 jdc "quickch: n=%d startw=%d curw=%d i = %d target=%d ", 1789 1.11 mrg n, startw, curw, i, target); 1790 1.7 cgd if ((target >= startw && target < curw) || target < top 1791 1.83 roy || target > bot) 1792 1.83 roy { 1793 1.64 jdc __CTRACE(__CTRACE_REFRESH, " notdirty\n"); 1794 1.71 roy __virtscr->alines[target]->flags &= ~__ISDIRTY; 1795 1.11 mrg } else 1796 1.11 mrg if ((n > 0 && target >= top && target < top + n) || 1797 1.83 roy (n < 0 && target <= bot && target > bot + n)) 1798 1.83 roy { 1799 1.65 blymn if (clp->hash != blank_hash || 1800 1.96 uwe !lineeq(clp->line, clp->line + 1, 1801 1.97 uwe (__virtscr->maxx - 1)) || 1802 1.122 blymn !_cursesi_celleq(clp->line, buf)) 1803 1.83 roy { 1804 1.65 blymn for (i = __virtscr->maxx; 1805 1.65 blymn i > BLANKSIZE; 1806 1.46 christos i -= BLANKSIZE) { 1807 1.65 blymn (void) memcpy(clp->line + i - 1808 1.46 christos BLANKSIZE, buf, sizeof(buf)); 1809 1.46 christos } 1810 1.115 rin (void)memcpy(clp->line, buf, 1811 1.115 rin i * sizeof(buf[0])); 1812 1.64 jdc __CTRACE(__CTRACE_REFRESH, 1813 1.64 jdc " blanked out: dirty\n"); 1814 1.11 mrg clp->hash = blank_hash; 1815 1.35 mycroft __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1); 1816 1.11 mrg } else { 1817 1.64 jdc __CTRACE(__CTRACE_REFRESH, 1818 1.64 jdc " -- blank line already: dirty\n"); 1819 1.35 mycroft __touchline(__virtscr, target, 0, (int) __virtscr->maxx - 1); 1820 1.11 mrg } 1821 1.5 cgd } else { 1822 1.64 jdc __CTRACE(__CTRACE_REFRESH, " -- dirty\n"); 1823 1.115 rin __touchline(__virtscr, target, 0, 1824 1.115 rin (int)__virtscr->maxx - 1); 1825 1.5 cgd } 1826 1.5 cgd if (target == cur_period) { 1827 1.5 cgd i = target + 1; 1828 1.71 roy tmp1 = curscr->alines[i]; 1829 1.5 cgd cur_period = i; 1830 1.5 cgd } else { 1831 1.5 cgd tmp1 = tmp2; 1832 1.5 cgd i = target; 1833 1.5 cgd } 1834 1.5 cgd } 1835 1.5 cgd #ifdef DEBUG 1836 1.64 jdc __CTRACE(__CTRACE_REFRESH, "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); 1837 1.11 mrg for (i = 0; i < curscr->maxy; i++) { 1838 1.64 jdc __CTRACE(__CTRACE_REFRESH, "C: %d:", i); 1839 1.11 mrg for (j = 0; j < curscr->maxx; j++) 1840 1.64 jdc __CTRACE(__CTRACE_REFRESH, "%c", 1841 1.71 roy curscr->alines[i]->line[j].ch); 1842 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 1843 1.64 jdc __CTRACE(__CTRACE_REFRESH, "W: %d:", i); 1844 1.23 jdc for (j = 0; j < __virtscr->maxx; j++) 1845 1.64 jdc __CTRACE(__CTRACE_REFRESH, "%c", 1846 1.71 roy __virtscr->alines[i]->line[j].ch); 1847 1.64 jdc __CTRACE(__CTRACE_REFRESH, "\n"); 1848 1.11 mrg } 1849 1.5 cgd #endif 1850 1.23 jdc if (n != 0) 1851 1.23 jdc scrolln(starts, startw, curs, bot, top); 1852 1.5 cgd } 1853 1.5 cgd 1854 1.5 cgd /* 1855 1.7 cgd * scrolln -- 1856 1.7 cgd * Scroll n lines, where n is starts - startw. 1857 1.5 cgd */ 1858 1.11 mrg static void /* ARGSUSED */ 1859 1.83 roy scrolln(int starts, int startw, int curs, int bot, int top) 1860 1.5 cgd { 1861 1.11 mrg int i, oy, ox, n; 1862 1.5 cgd 1863 1.5 cgd oy = curscr->cury; 1864 1.5 cgd ox = curscr->curx; 1865 1.5 cgd n = starts - startw; 1866 1.5 cgd 1867 1.7 cgd /* 1868 1.7 cgd * XXX 1869 1.7 cgd * The initial tests that set __noqch don't let us reach here unless 1870 1.41 jdc * we have either cs + ho + SF/sf/SR/sr, or AL + DL. SF/sf and SR/sr 1871 1.7 cgd * scrolling can only shift the entire scrolling region, not just a 1872 1.7 cgd * part of it, which means that the quickch() routine is going to be 1873 1.41 jdc * sadly disappointed in us if we don't have cs as well. 1874 1.7 cgd * 1875 1.41 jdc * If cs, ho and SF/sf are set, can use the scrolling region. Because 1876 1.41 jdc * the cursor position after cs is undefined, we need ho which gives us 1877 1.7 cgd * the ability to move to somewhere without knowledge of the current 1878 1.7 cgd * location of the cursor. Still call __mvcur() anyway, to update its 1879 1.7 cgd * idea of where the cursor is. 1880 1.7 cgd * 1881 1.7 cgd * When the scrolling region has been set, the cursor has to be at the 1882 1.7 cgd * last line of the region to make the scroll happen. 1883 1.7 cgd * 1884 1.7 cgd * Doing SF/SR or AL/DL appears faster on the screen than either sf/sr 1885 1.41 jdc * or AL/DL, and, some terminals have AL/DL, sf/sr, and cs, but not 1886 1.7 cgd * SF/SR. So, if we're scrolling almost all of the screen, try and use 1887 1.7 cgd * AL/DL, otherwise use the scrolling region. The "almost all" is a 1888 1.7 cgd * shameless hack for vi. 1889 1.7 cgd */ 1890 1.5 cgd if (n > 0) { 1891 1.72 roy if (change_scroll_region != NULL && cursor_home != NULL && 1892 1.72 roy (parm_index != NULL || 1893 1.72 roy ((parm_insert_line == NULL || parm_delete_line == NULL || 1894 1.41 jdc top > 3 || bot + 3 < __virtscr->maxy) && 1895 1.72 roy scroll_forward != NULL))) 1896 1.72 roy { 1897 1.75 roy tputs(tiparm(change_scroll_region, top, bot), 1898 1.72 roy 0, __cputchar); 1899 1.7 cgd __mvcur(oy, ox, 0, 0, 1); 1900 1.72 roy tputs(cursor_home, 0, __cputchar); 1901 1.7 cgd __mvcur(0, 0, bot, 0, 1); 1902 1.72 roy if (parm_index != NULL) 1903 1.75 roy tputs(tiparm(parm_index, n), 1904 1.72 roy 0, __cputchar); 1905 1.7 cgd else 1906 1.7 cgd for (i = 0; i < n; i++) 1907 1.72 roy tputs(scroll_forward, 0, __cputchar); 1908 1.75 roy tputs(tiparm(change_scroll_region, 1909 1.83 roy 0, (int)__virtscr->maxy - 1), 0, __cputchar); 1910 1.7 cgd __mvcur(bot, 0, 0, 0, 1); 1911 1.72 roy tputs(cursor_home, 0, __cputchar); 1912 1.7 cgd __mvcur(0, 0, oy, ox, 1); 1913 1.7 cgd return; 1914 1.7 cgd } 1915 1.7 cgd 1916 1.7 cgd /* Scroll up the block. */ 1917 1.72 roy if (parm_index != NULL && top == 0) { 1918 1.7 cgd __mvcur(oy, ox, bot, 0, 1); 1919 1.75 roy tputs(tiparm(parm_index, n), 0, __cputchar); 1920 1.7 cgd } else 1921 1.72 roy if (parm_delete_line != NULL) { 1922 1.11 mrg __mvcur(oy, ox, top, 0, 1); 1923 1.75 roy tputs(tiparm(parm_delete_line, n), 1924 1.72 roy 0, __cputchar); 1925 1.11 mrg } else 1926 1.72 roy if (delete_line != NULL) { 1927 1.11 mrg __mvcur(oy, ox, top, 0, 1); 1928 1.11 mrg for (i = 0; i < n; i++) 1929 1.83 roy tputs(delete_line, 0, 1930 1.83 roy __cputchar); 1931 1.11 mrg } else 1932 1.72 roy if (scroll_forward != NULL && top == 0) { 1933 1.11 mrg __mvcur(oy, ox, bot, 0, 1); 1934 1.11 mrg for (i = 0; i < n; i++) 1935 1.72 roy tputs(scroll_forward, 0, 1936 1.41 jdc __cputchar); 1937 1.11 mrg } else 1938 1.11 mrg abort(); 1939 1.5 cgd 1940 1.7 cgd /* Push down the bottom region. */ 1941 1.5 cgd __mvcur(top, 0, bot - n + 1, 0, 1); 1942 1.72 roy if (parm_insert_line != NULL) 1943 1.75 roy tputs(tiparm(parm_insert_line, n), 0, __cputchar); 1944 1.83 roy else { 1945 1.83 roy if (insert_line != NULL) { 1946 1.11 mrg for (i = 0; i < n; i++) 1947 1.72 roy tputs(insert_line, 0, __cputchar); 1948 1.83 roy } else 1949 1.11 mrg abort(); 1950 1.83 roy } 1951 1.5 cgd __mvcur(bot - n + 1, 0, oy, ox, 1); 1952 1.5 cgd } else { 1953 1.7 cgd /* 1954 1.7 cgd * !!! 1955 1.7 cgd * n < 0 1956 1.7 cgd * 1957 1.41 jdc * If cs, ho and SR/sr are set, can use the scrolling region. 1958 1.7 cgd * See the above comments for details. 1959 1.7 cgd */ 1960 1.72 roy if (change_scroll_region != NULL && cursor_home != NULL && 1961 1.72 roy (parm_rindex != NULL || 1962 1.72 roy ((parm_insert_line == NULL || parm_delete_line == NULL || 1963 1.72 roy top > 3 || 1964 1.72 roy bot + 3 < __virtscr->maxy) && scroll_reverse != NULL))) 1965 1.72 roy { 1966 1.75 roy tputs(tiparm(change_scroll_region, top, bot), 1967 1.72 roy 0, __cputchar); 1968 1.7 cgd __mvcur(oy, ox, 0, 0, 1); 1969 1.72 roy tputs(cursor_home, 0, __cputchar); 1970 1.7 cgd __mvcur(0, 0, top, 0, 1); 1971 1.7 cgd 1972 1.72 roy if (parm_rindex != NULL) 1973 1.75 roy tputs(tiparm(parm_rindex, -n), 1974 1.72 roy 0, __cputchar); 1975 1.7 cgd else 1976 1.7 cgd for (i = n; i < 0; i++) 1977 1.72 roy tputs(scroll_reverse, 0, __cputchar); 1978 1.75 roy tputs(tiparm(change_scroll_region, 1979 1.73 roy 0, (int) __virtscr->maxy - 1), 0, __cputchar); 1980 1.7 cgd __mvcur(top, 0, 0, 0, 1); 1981 1.72 roy tputs(cursor_home, 0, __cputchar); 1982 1.7 cgd __mvcur(0, 0, oy, ox, 1); 1983 1.7 cgd return; 1984 1.7 cgd } 1985 1.7 cgd 1986 1.7 cgd /* Preserve the bottom lines. */ 1987 1.7 cgd __mvcur(oy, ox, bot + n + 1, 0, 1); 1988 1.72 roy if (parm_rindex != NULL && bot == __virtscr->maxy) 1989 1.75 roy tputs(tiparm(parm_rindex, -n), 0, __cputchar); 1990 1.83 roy else { 1991 1.72 roy if (parm_delete_line != NULL) 1992 1.75 roy tputs(tiparm(parm_delete_line, -n), 1993 1.72 roy 0, __cputchar); 1994 1.83 roy else { 1995 1.72 roy if (delete_line != NULL) 1996 1.11 mrg for (i = n; i < 0; i++) 1997 1.72 roy tputs(delete_line, 1998 1.72 roy 0, __cputchar); 1999 1.83 roy else { 2000 1.72 roy if (scroll_reverse != NULL && 2001 1.41 jdc bot == __virtscr->maxy) 2002 1.11 mrg for (i = n; i < 0; i++) 2003 1.72 roy tputs(scroll_reverse, 0, 2004 1.41 jdc __cputchar); 2005 1.11 mrg else 2006 1.11 mrg abort(); 2007 1.83 roy } 2008 1.83 roy } 2009 1.83 roy } 2010 1.7 cgd /* Scroll the block down. */ 2011 1.5 cgd __mvcur(bot + n + 1, 0, top, 0, 1); 2012 1.72 roy if (parm_insert_line != NULL) 2013 1.75 roy tputs(tiparm(parm_insert_line, -n), 0, __cputchar); 2014 1.5 cgd else 2015 1.72 roy if (insert_line != NULL) 2016 1.11 mrg for (i = n; i < 0; i++) 2017 1.72 roy tputs(insert_line, 0, __cputchar); 2018 1.11 mrg else 2019 1.11 mrg abort(); 2020 1.5 cgd __mvcur(top, 0, oy, ox, 1); 2021 1.19 jdc } 2022 1.19 jdc } 2023 1.19 jdc 2024 1.19 jdc /* 2025 1.23 jdc * __unsetattr -- 2026 1.19 jdc * Unset attributes on curscr. Leave standout, attribute and colour 2027 1.41 jdc * modes if necessary (!ms). Always leave altcharset (xterm at least 2028 1.19 jdc * ignores a cursor move if we don't). 2029 1.19 jdc */ 2030 1.23 jdc void /* ARGSUSED */ 2031 1.23 jdc __unsetattr(int checkms) 2032 1.19 jdc { 2033 1.19 jdc int isms; 2034 1.19 jdc 2035 1.83 roy if (checkms) { 2036 1.83 roy if (!move_standout_mode) 2037 1.19 jdc isms = 1; 2038 1.83 roy else 2039 1.19 jdc isms = 0; 2040 1.83 roy } else 2041 1.19 jdc isms = 1; 2042 1.64 jdc __CTRACE(__CTRACE_REFRESH, 2043 1.64 jdc "__unsetattr: checkms = %d, ms = %s, wattr = %08x\n", 2044 1.72 roy checkms, move_standout_mode ? "TRUE" : "FALSE", curscr->wattr); 2045 1.65 blymn 2046 1.20 jdc /* 2047 1.65 blymn * Don't leave the screen in standout mode (check against ms). Check 2048 1.27 mycroft * to see if we also turn off underscore, attributes and colour. 2049 1.20 jdc */ 2050 1.19 jdc if (curscr->wattr & __STANDOUT && isms) { 2051 1.72 roy tputs(exit_standout_mode, 0, __cputchar); 2052 1.41 jdc curscr->wattr &= __mask_se; 2053 1.19 jdc } 2054 1.20 jdc /* 2055 1.41 jdc * Don't leave the screen in underscore mode (check against ms). 2056 1.26 jdc * Check to see if we also turn off attributes. Assume that we 2057 1.26 jdc * also turn off colour. 2058 1.20 jdc */ 2059 1.19 jdc if (curscr->wattr & __UNDERSCORE && isms) { 2060 1.72 roy tputs(exit_underline_mode, 0, __cputchar); 2061 1.41 jdc curscr->wattr &= __mask_ue; 2062 1.19 jdc } 2063 1.20 jdc /* 2064 1.41 jdc * Don't leave the screen with attributes set (check against ms). 2065 1.26 jdc * Assume that also turn off colour. 2066 1.20 jdc */ 2067 1.20 jdc if (curscr->wattr & __TERMATTR && isms) { 2068 1.72 roy tputs(exit_attribute_mode, 0, __cputchar); 2069 1.41 jdc curscr->wattr &= __mask_me; 2070 1.19 jdc } 2071 1.41 jdc /* Don't leave the screen with altcharset set (don't check ms). */ 2072 1.19 jdc if (curscr->wattr & __ALTCHARSET) { 2073 1.72 roy tputs(exit_alt_charset_mode, 0, __cputchar); 2074 1.19 jdc curscr->wattr &= ~__ALTCHARSET; 2075 1.19 jdc } 2076 1.41 jdc /* Don't leave the screen with colour set (check against ms). */ 2077 1.47 jdc if (__using_color && isms) 2078 1.47 jdc __unset_color(curscr); 2079 1.1 cgd } 2080 1.65 blymn 2081 1.65 blymn /* compare two line segments */ 2082 1.95 uwe static int 2083 1.95 uwe lineeq(__LDATA *xl, __LDATA *yl, size_t len) 2084 1.65 blymn { 2085 1.65 blymn int i = 0; 2086 1.65 blymn __LDATA *xp = xl, *yp = yl; 2087 1.65 blymn 2088 1.83 roy for (i = 0; i < len; i++, xp++, yp++) { 2089 1.122 blymn if (!_cursesi_celleq(xp, yp)) 2090 1.65 blymn return 0; 2091 1.65 blymn } 2092 1.65 blymn return 1; 2093 1.65 blymn } 2094 1.65 blymn 2095 1.119 blymn #ifdef HAVE_WCHAR 2096 1.65 blymn /* 2097 1.65 blymn * Output the non-spacing characters associated with the given character 2098 1.65 blymn * cell to the screen. 2099 1.65 blymn */ 2100 1.65 blymn 2101 1.65 blymn void 2102 1.65 blymn __cursesi_putnsp(nschar_t *nsp, const int wy, const int wx) 2103 1.65 blymn { 2104 1.65 blymn nschar_t *p; 2105 1.65 blymn 2106 1.66 blymn /* this shuts up gcc warnings about wx and wy not being used */ 2107 1.66 blymn if (wx > wy) { 2108 1.66 blymn } 2109 1.66 blymn 2110 1.65 blymn p = nsp; 2111 1.65 blymn while (p != NULL) { 2112 1.83 roy __cputwchar((int)p->ch); 2113 1.65 blymn __CTRACE(__CTRACE_REFRESH, 2114 1.115 rin "_cursesi_putnsp: (%d,%d) non-spacing putwchar(0x%x)\n", 2115 1.115 rin wy, wx - 1, p->ch); 2116 1.65 blymn p = p->next; 2117 1.65 blymn } 2118 1.65 blymn } 2119 1.65 blymn 2120 1.65 blymn #endif /* HAVE_WCHAR */ 2121