[BACK]Return to refresh.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libcurses

Annotation of src/lib/libcurses/refresh.c, Revision 1.116

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

CVSweb <webmaster@jp.NetBSD.org>